Actions sind Sveltes Mechanismus, um eigenes Verhalten an ein DOM-Element zu hängen. Du schreibst eine ganz normale Funktion und attachst sie mit use:meineFunktion={...} an ein HTML-Element — Svelte ruft sie auf, sobald das Element im DOM landet, und gibt dir die Möglichkeit, beim Verschwinden wieder aufzuräumen. Klassische Anwendungsfälle: Drittanbieter-Bibliotheken integrieren, Tooltips bauen, Klick-außerhalb-Erkennung, Focus-Management. Dieser Artikel erklärt das Grundprinzip.
Wofür Actions?
Komponenten haben ein eigenes Mounting-Lifecycle (onMount, onDestroy, $effect). Aber manchmal willst du Verhalten an einzelne DOM-Elemente hängen — wiederverwendbar, ohne ständig dieselben Listener-Setups zu kopieren.
Drei typische Beispiele:
- Tooltip: Beim Hover soll ein kleines Popup erscheinen — gleicher Code an dutzenden Buttons.
- Klick außerhalb: Ein Dropdown soll sich schließen, wenn der Nutzer woanders klickt.
- Library-Integration: Eine Datepicker- oder Editor-Library braucht ein Element, an das sie sich hängt.
Statt jedes Mal bind:this, onMount, Listener-Setup, onDestroy zu schreiben, packst du das in eine Action — und benutzt sie überall mit einem einzigen use:.
Die einfachste Action
<script>
function logMount(node) {
console.log('Element gemountet:', node);
}
</script>
<div use:logMount>Hallo</div>Was hier passiert:
logMountist eine normale Funktion, die als erstes Argument den DOM-Knoten bekommt.use:logMountan einem Element ruft die Funktion auf, sobald dieses Element im DOM ist.- Du musst nichts importieren, kein Lifecycle-Hook, kein
bind:this. Action und Element sind zusammengeführt.
Cleanup mit $effect
Realistischere Actions wollen beim Mount etwas einrichten und beim Unmount wieder aufräumen — typisch Listener oder Observer. Dafür nutzt man innerhalb der Action $effect:
<script>
function logClicks(node) {
$effect(() => {
function handle() {
console.log('Klick auf', node.tagName);
}
node.addEventListener('click', handle);
return () => node.removeEventListener('click', handle);
});
}
</script>
<button use:logClicks>Klick mich</button>Schritt für Schritt:
logClickswird beim Mount aufgerufen, mit dem<button>-Knoten.$effectregistriert den Listener.- Wenn der Button später aus dem DOM verschwindet, läuft die Cleanup-Funktion und entfernt den Listener wieder.
Mit Parameter
Actions können Daten von außen entgegennehmen — über das gleiche use:-Konstrukt:
<script>
function autoFocus(node, options = { delay: 0 }) {
$effect(() => {
const id = setTimeout(() => node.focus(), options.delay);
return () => clearTimeout(id);
});
}
</script>
<input use:autoFocus={{ delay: 200 }} />{ delay: 200 } wird als zweites Argument an autoFocus durchgereicht. Wie auf Parameter-Updates reagiert wird (also wenn sich der Wert während der Lebenszeit ändert), zeigt der Artikel Action-Parameter & Updates.
Mehrere Actions am selben Element
Du kannst beliebig viele Actions am gleichen Element kombinieren — use: lässt sich mehrfach setzen:
<button use:autoFocus={{ delay: 100 }} use:logClicks use:tooltip={{ text: 'Speichern' }}>
Speichern
</button>Jede Action läuft unabhängig, jede räumt selbst hinter sich auf. Genau das macht sie wiederverwendbar und kombinierbar.
Wichtige Eigenschaften
| Eigenschaft | Verhalten |
|---|---|
| Läuft im SSR | Nein. Actions sind eine Browser-Sache. |
| Läuft pro Element-Mount | Genau einmal pro Mount-Vorgang. |
| Reaktivität auf Parameter | Nur in $effect innerhalb der Action. |
| Cleanup | Über die Cleanup-Rückgabe in $effect (oder destroy() im Legacy-Stil). |
| Mehrfach pro Element | Ja, mit mehreren use:. |
| Action vs. Komponente | Action: hängt Verhalten an existierendes Element. Komponente: rendert eigenes Markup. |
Typische Anwendungsfälle
- Tooltips — bei Hover ein Popup einblenden.
- Klick-außerhalb-Erkennung — Dropdowns, Modals.
- Focus-Management — Focus-Trap, Auto-Focus, Tab-Order.
- Drag-and-Drop — Mouse-/Pointer-Listener am Drag-Handle.
- Lazy-Loading — IntersectionObserver am Element.
- Bibliotheks-Integration — Datepicker, Tagify, Quill, Mapbox usw. brauchen ein DOM-Element zum Initialisieren.
- Long-press / Swipe — Geste-Erkennung.
- Auto-Resize von Textareas — Content-fit per
scrollHeight.
Vertieft im Artikel Praxis-Actions.
Action vs. Komponente — wann was?
Beide kapseln wiederverwendbares Verhalten, aber mit unterschiedlichem Fokus:
| Situation | Empfehlung |
|---|---|
| Verhalten an einem bestehenden Element | Action |
| Eigenes Markup mit eigener Struktur | Komponente |
| An mehreren verschiedenen Element-Typen einsetzbar | Action |
| Hat eigenen sichtbaren UI-Anteil | Komponente |
| Drittanbieter-Library, die ein Element bekommt | Action |
| Komplexe State-Logik mit eigenem Markup | Komponente |
Faustregel: Wenn du nur Verhalten und keine Struktur lieferst, ist eine Action die richtige Wahl.
Interessantes
Action im Top-Level eines .ts-Modul direkt aufrufen.
Actions sind Funktionen, die Svelte beim Mount aufruft — du rufst sie nicht selbst auf. use:meineAction ist der Aufruf.
onMount/onDestroy innerhalb einer Action verwenden.
Lifecycle-Hooks gehören zur Komponente. In Actions arbeitest du mit $effect.
Vergessenes Cleanup.
Wenn deine Action Listener oder Observer registriert, ohne sie zu entfernen, leckt jeder Mount Ressourcen. Cleanup-Rückgabe in $effect ist Pflicht.
Mit node.parentElement arbeiten zu früh.
Beim ersten Aufruf der Action ist das Element zwar im DOM, aber Layout und Geschwister sind je nach Render-Phase noch in Bewegung. Wer auf Eltern-Größen oder -Positionen angewiesen ist, schreibt das in $effect und nicht ins Action-Top-Level.
Vergessen, dass Actions im SSR übersprungen werden.
Code in einer Action läuft nur im Browser. Server-spezifische Logik gehört woanders hin (z. B. in eine load-Funktion).