Wenn dir jemand sagt „in Svelte machst du Events einfach mit onclick”, ist das nur ein Drittel der Wahrheit. In einer real gewachsenen Anwendung begegnen dir drei verschiedene Arten von Events, die zwar ähnlich aussehen, aber unterschiedlich funktionieren — und unterschiedliche Aufgaben haben. Dieser Artikel ordnet die drei Welten ein, damit du immer weißt, mit welcher Art du es gerade zu tun hast.

Die drei Arten von Events

Wenn der Nutzer auf einen Button klickt, eine Taste drückt oder ein Formular abschickt, passiert immer das Gleiche: Es passiert etwas, und dein Code soll darauf reagieren. Aber wer das Event auslöst und wer es empfängt, ist unterschiedlich.

ArtWer löst aus?Wer empfängt?Beispiel
DOM-EventDer Browser (Klick, Tastatur …)Dein Markup-Element<button onclick={handle}>
Component-EventEine deiner KomponentenDie Eltern-Komponente<MyForm onSave={...} />
Custom DOM-EventDu, im JavaScript-CodeBeliebige andere DOM-Elementeel.dispatchEvent(new CustomEvent(...))

Auf den ersten Blick sehen alle drei wie „dieselbe Sache” aus. Aber sie spielen ganz unterschiedliche Rollen.

DOM-Events – die Standardklasse

DOM-Events sind die Events, die der Browser selbst auslöst. Du klickst, der Browser ruft deinen Handler auf:

svelte DOM-Event
<button onclick={() => console.log('geklickt')}>
    Klick mich
</button>

Der Schlüssel: Der Browser weiß von ganz allein, wann ein Klick passiert. Du musst ihm nur mitteilen, was dann passieren soll. Dasselbe gilt für onkeydown, oninput, onsubmit, onmousemove und Dutzende weitere.

Eine vollständige Übersicht und vertieftes Wissen zu DOM-Events findest du im Artikel DOM-Events vertieft. Die Syntax-Grundlagen stehen im Artikel Events (Components).

Component-Events – wenn deine Komponente etwas „mitteilt”

Wenn eine Kind-Komponente der Eltern-Komponente etwas mitteilen will (z. B. „der Nutzer hat auf Speichern geklickt”), funktioniert das in Svelte 5 als Callback-Prop:

svelte Kind-Komponente: SaveButton.svelte
<script>
    let { onSave } = $props();
</script>

<button onclick={() => onSave?.({ time: Date.now() })}>
    Speichern
</button>
svelte Eltern-Komponente
<SaveButton onSave={(detail) => console.log('Gespeichert um', detail.time)} />

Das Schöne: Im Aufruf sieht es genauso aus wie ein DOM-Event (onSave={...}). Die Eltern-Komponente muss nicht wissen, ob SaveButton einen echten Browser-Klick weiterreicht oder etwas Eigenes meldet — die Schreibweise bleibt identisch.

In Svelte 4 gab es dafür createEventDispatcher. In Svelte 5 ist es einfach eine ganz normale Funktion, die du als Prop übergibst. Mehr dazu im Artikel Events (Components).

Custom DOM Events – wenn DOM-Elemente miteinander reden sollen

Es gibt einen seltenen, aber sehr nützlichen Spezialfall: Du willst, dass ein DOM-Element ein eigenes Event abschickt, das im DOM nach oben blubbert (Bubbling) — sodass beliebige Vorfahren es einfangen können, ohne dass du Props verkettest.

svelte Custom Event auslösen
<script>
    let button;

    function fire() {
        button.dispatchEvent(
            new CustomEvent('user-action', {
                detail: { action: 'beispiel' },
                bubbles: true,
            })
        );
    }
</script>

<div onuser-action={(e) => console.log('Gefangen:', e.detail)}>
    <button bind:this={button} onclick={fire}>
        Eigenes Event auslösen
    </button>
</div>

Das wirkt zunächst exotisch, ist aber ein verbreitetes Pattern für Komponenten-Bibliotheken oder für Kommunikation zwischen Insel-Komponenten in Astro/SSR-Setups. Vollständig erklärt im Artikel Custom DOM Events.

Wann verwendet man was?

Eine kurze Entscheidungshilfe:

  • Reaktion auf Nutzerinteraktion (Klick, Tastatur, Hover): DOM-Event.
  • Eine Komponente meldet etwas an ihre Eltern-Komponente: Component-Event als Callback-Prop.
  • Mehrere unabhängige Stellen sollen etwas mitbekommen, ohne dass sie direkt Eltern/Kind sind: Custom DOM Event mit Bubbling — oder ein State-Container/Store.

In 95 % der Fälle reichen DOM-Events und Component-Events. Custom DOM Events sind die Lösung für die übrigen 5 %.

Was ist mit Modifiern wie |preventDefault?

Wer aus Svelte 4 kommt, kennt vielleicht die Modifier-Syntax: on:click|preventDefault={save}. Die gibt es in Svelte 5 nicht mehr. Stattdessen schreibst du die Logik direkt in den Handler:

svelte Form-Submit ohne Reload
<form onsubmit={(e) => { e.preventDefault(); save(); }}>
    ...
</form>

Welche Modifier es gab, wodurch sie ersetzt werden und welche Hilfsmuster es für once, stopPropagation, capture und passive gibt, steht im Artikel Modifier-Patterns.

Häufige Verwirrungen

„Warum geht on:click nicht mehr?” Im Svelte-5-Runes-Modus wird onclick ohne Doppelpunkt geschrieben — exakt wie das HTML-Attribut. Im Legacy-Modus geht beides.

„Wieso haben Component-Events kein event.detail?” In Svelte 4 dispatchten Komponenten ein echtes Event-Objekt mit event.detail. In Svelte 5 sind es gewöhnliche Funktionsaufrufe — der Wert kommt direkt als Argument. Statt e.detail.value schreibst du einfach (value) => ....

„Wie höre ich von einem entfernten Component zu, ohne Props weiterzureichen?” Drei Möglichkeiten:

  • Context-API für nahe verwandte Komponenten (Context API).
  • Stores oder ein gemeinsamer $state-Container für globale Werte (Stores).
  • Custom DOM Events mit Bubbling, wenn die Verbindung über DOM-Hierarchie läuft.

Weiterführende Ressourcen

Externe Quellen

Verwandte Artikel

/ Weiter

Zurück zu Events

Zur Übersicht