Kurs Svelte i SvelteKit · Moduł 10: Akcje
Mjölnir - Actions
W tej lekcji4
Witaj w kuźni Mjölnira! Młot Thora ma niezwykłe moce. Actions w Svelte to właśnie takie moce - rozszerzają możliwości elementów DOM.
Czym są Actions?
Actions to funkcje wywoływane, gdy element zostaje zamontowany w DOM. W Svelte 5 konfigurację i sprzątanie umieszczasz w $effect wewnątrz akcji - funkcja zwrócona z $effect uruchomi się, gdy element zniknie:
<script>
function myAction(node) {
// node to element DOM - już jest w dokumencie
console.log('Element zamontowany:', node);
$effect(() => {
// tu konfiguracja: listenery, biblioteki
return () => {
// a tu sprzątanie, gdy element znika
console.log('Element odmontowany');
};
});
}
</script>
<div use:myAction>
Element z akcją
</div>Akcje nie działają podczas renderowania na serwerze (SSR) - uruchamiają się dopiero w przeglądarce.
Klasyczne API: obiekt z destroy
Zanim pojawił się $effect, akcja zwracała obiekt z metodą destroy() (i update(), o której w następnej lekcji). To API nadal działa i przydaje się w zwykłych plikach .js - runy, takie jak $effect, są dostępne tylko w plikach .svelte i .svelte.js.
// actions.js - zwykły plik JS, bez runów
export function myAction(node) {
console.log('Element zamontowany:', node);
return {
destroy() {
console.log('Element odmontowany');
}
};
}Przykład: Click Outside
// actions.js
export function clickOutside(node, callback) {
function handleClick(event) {
if (!node.contains(event.target)) {
callback();
}
}
document.addEventListener('click', handleClick, true);
return {
destroy() {
document.removeEventListener('click', handleClick, true);
}
};
}<script>
import { clickOutside } from './actions.js';
let isOpen = $state(false);
</script>
{#if isOpen}
<div use:clickOutside={() => isOpen = false} class="dropdown">
Kliknij poza mną żeby zamknąć
</div>
{/if}Akcje z parametrami
<script>
function tooltip(node, text) {
let tooltipEl;
function show() {
tooltipEl = document.createElement('div');
tooltipEl.className = 'tooltip';
tooltipEl.textContent = text;
document.body.appendChild(tooltipEl);
const rect = node.getBoundingClientRect();
tooltipEl.style.left = rect.left + 'px';
tooltipEl.style.top = rect.bottom + 5 + 'px';
}
function hide() {
tooltipEl?.remove();
}
$effect(() => {
node.addEventListener('mouseenter', show);
node.addEventListener('mouseleave', hide);
return () => {
hide();
node.removeEventListener('mouseenter', show);
node.removeEventListener('mouseleave', hide);
};
});
}
</script>
<button use:tooltip={'To jest przycisk'}>
Najedź na mnie
</button>Mjölnir daje moc - Actions dają moc elementom!
Kod do tej lekcji: App.svelte
<script>
// Mjölnir - Moce przypisane do elementów
// use:action - dodatkowe zachowania DOM
// Prosta akcja - focus na mount
function autofocus(node) {
node.focus();
// Sprzątanie w Svelte 5: funkcja zwrócona z $effect
$effect(() => {
return () => console.log('Element usunięty');
});
}
// Akcja z parametrami
function tooltip(node, text) {
let tooltipEl;
function show() {
tooltipEl = document.createElement('div');
tooltipEl.textContent = text;
tooltipEl.className = 'tooltip';
document.body.appendChild(tooltipEl);
const rect = node.getBoundingClientRect();
tooltipEl.style.left = rect.left + rect.width / 2 + 'px';
tooltipEl.style.top = rect.top - 10 + 'px';
}
function hide() {
if (tooltipEl) {
tooltipEl.remove();
tooltipEl = null;
}
}
node.addEventListener('mouseenter', show);
node.addEventListener('mouseleave', hide);
// Klasyczne API akcji (nadal działa): update i destroy
return {
// update - gdy parametr się zmieni
update(newText) {
text = newText;
},
// cleanup
destroy() {
hide();
node.removeEventListener('mouseenter', show);
node.removeEventListener('mouseleave', hide);
}
};
}
let tooltipText = $state('Jestem tooltipem!');
</script>
<main class="mjolnir">
<h1>Mjölnir - Actions</h1>
<p class="subtitle">use: - dodaj moce do elementów</p>
<section>
<h2>use:autofocus</h2>
<input use:autofocus placeholder="Auto-fokus na start!" />
</section>
<section>
<h2>use:tooltip</h2>
<input
bind:value={tooltipText}
placeholder="Zmień tekst tooltipa"
/>
<button use:tooltip={tooltipText}>
Najedź na mnie!
</button>
</section>
</main>
<style>
.mjolnir {
font-family: 'Georgia', serif;
max-width: 500px;
margin: 0 auto;
padding: 2rem;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
color: #e8e8f7;
min-height: 100vh;
}
h1 {
color: #7cb3f0;
text-align: center;
}
.subtitle {
text-align: center;
color: #6a8ab9;
}
section {
background: rgba(124, 179, 240, 0.1);
border: 1px solid #7cb3f0;
border-radius: 8px;
padding: 1rem;
margin: 1rem 0;
}
h2 {
color: #7cb3f0;
font-size: 1rem;
margin-top: 0;
}
input {
width: 100%;
padding: 0.75rem;
background: rgba(0,0,0,0.3);
border: 1px solid #3a5f8a;
border-radius: 4px;
color: #e8e8f7;
margin-bottom: 0.5rem;
}
input:focus {
border-color: #7cb3f0;
outline: none;
}
button {
padding: 0.75rem 1.5rem;
background: #3a5f8a;
color: #e8e8f7;
border: 1px solid #7cb3f0;
border-radius: 4px;
cursor: pointer;
}
:global(.tooltip) {
position: fixed;
background: #ffd700;
color: #1a1a2e;
padding: 0.5rem 1rem;
border-radius: 4px;
font-size: 0.9rem;
transform: translate(-50%, -100%);
z-index: 1000;
pointer-events: none;
}
</style>Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Jak używamy action na elemencie DOM?
2. Co może zwrócić funkcja action?