Bindings auf Komponenten erlauben dem Eltern-Komponenten direkten Zugriff auf Werte und Funktionen einer Kind-Komponente. Es gibt zwei Hauptformen: bind:value für zwei-weg-gebundene Props (kombiniert mit $bindable) und bind:this für eine Referenz auf die Komponenten-Instanz, über die exportierte Methoden aufgerufen werden können. Dieser Artikel zeigt beide Patterns mit Praxis-Beispielen.

bind:value mit $bindable

In der Kind-Komponente wird die Prop mit $bindable markiert:

svelte NumberInput.svelte
<script>
    let { value = $bindable(0) } = $props();
</script>

<input type="number" bind:value />

Im Eltern wird die Two-Way-Variante mit bind:value={...} genutzt:

svelte Verwendung
<script>
    import NumberInput from '$lib/components/NumberInput.svelte';
    let count = $state(0);
</script>

<NumberInput bind:value={count} />
<p>{count}</p>

Updates der Kind-Komponente propagieren automatisch nach count im Eltern. Tieferes zur Rune im Artikel $bindable.

bind:this – Zugriff auf die Instanz

Wenn der Eltern-Komponent eine Methode der Kind-Komponente aufrufen will (z. B. focus(), scrollToBottom(), play()), greift er per bind:this auf die Instanz zu:

svelte VideoPlayer.svelte
<script>
    let { src } = $props();
    let videoElement;

    export function play() {
        videoElement.play();
    }

    export function pause() {
        videoElement.pause();
    }
</script>

<video bind:this={videoElement} {src} controls />

Die Funktionen werden mit export function aus der Komponente herausgereicht. Im Eltern:

svelte Eltern-Komponent
<script>
    import VideoPlayer from '$lib/components/VideoPlayer.svelte';
    let player;
</script>

<VideoPlayer bind:this={player} src="/clip.mp4" />

<button onclick={() => player?.play()}>Abspielen</button>
<button onclick={() => player?.pause()}>Pause</button>

Wichtig: player enthält nicht die Komponente selbst, sondern ein Objekt mit ihren exportierten Werten und Funktionen.

Exportierte Werte vs. Methoden

Auch nicht-Funktionen lassen sich aus einer Komponente exportieren:

svelte ScrollList.svelte
<script>
    let container;
    let scrollTop = $state(0);

    export function scrollToTop() {
        container.scrollTo({ top: 0, behavior: 'smooth' });
    }

    export { scrollTop };
</script>

<div bind:this={container} onscroll={(e) => scrollTop = e.currentTarget.scrollTop}>
    <slot />
</div>
svelte Eltern liest scrollTop
<script>
    let list;
</script>

<ScrollList bind:this={list}>...</ScrollList>

<p>Scroll: {list?.scrollTop ?? 0}</p>
<button onclick={() => list?.scrollToTop()}>Nach oben</button>

Wann bind:value, wann Callback-Prop?

Sobald sich eine Prop sinnvoll bidirektional beschreiben lässt (Form-Wert, Picker, Slider), ist $bindable + bind:value ergonomischer.

Sobald Side Effects oder Validierung im Eltern nötig sind, gibt eine Callback-Prop mehr Kontrolle:

svelte Callback statt Bind
<NumberInput
    value={count}
    onChange={(next) => {
        if (next > 100) return; // Validierung
        count = next;
        analytics.track('count-changed', next);
    }}
/>

TypeScript-Typen für exports

Bei lang="ts" werden exportierte Werte typisiert übernommen. Der Type, den bind:this zurückgibt, lässt sich über ComponentExports aus svelte ableiten:

svelte Eltern-Komponent (TypeScript)
<script lang="ts">
    import VideoPlayer from '$lib/components/VideoPlayer.svelte';
    import type { ComponentExports } from 'svelte';

    let player: ComponentExports<typeof VideoPlayer> | undefined = $state();
</script>

<VideoPlayer bind:this={player} src="/clip.mp4" />
<button onclick={() => player?.play()}>Play</button>

Praxis-Beispiel: Modal mit imperativer API

svelte Modal.svelte
<script>
    let { children } = $props();
    let dialog;
    let isOpen = $state(false);

    export function open() {
        dialog.showModal();
        isOpen = true;
    }

    export function close() {
        dialog.close();
        isOpen = false;
    }
</script>

<dialog bind:this={dialog} onclose={() => isOpen = false}>
    {@render children()}
</dialog>
svelte Verwendung
<script>
    let modal;
</script>

<button onclick={() => modal.open()}>Öffnen</button>

<Modal bind:this={modal}>
    <h2>Hallo</h2>
    <button onclick={() => modal.close()}>Schließen</button>
</Modal>

Migration aus Svelte 4

In Svelte 4 war jede export let-Variable implizit bindbar:

svelte Svelte 4 (alt)
<!-- Kind -->
<script>
    export let value = 0;
</script>

<input bind:value />

<!-- Eltern -->
<NumberInput bind:value={count} />

In Svelte 5 muss die bindbare Prop explizit markiert werden — siehe $bindable.

bind:this funktioniert weiterhin — gibt aber kein Klasseninstanz-Objekt mehr zurück, sondern ein Plain-Object aus den exportierten Werten/Funktionen.

Häufige Stolperfallen

bind:value ohne $bindable. Compiler-Fehler. Die Prop muss explizit als bindbar markiert werden.

bind:this mit Klasseninstanz-Erwartung. Aus Svelte 4 gewohnt: instance.$set({...}) etc. — gibt es in Svelte 5 nicht mehr. Stattdessen exportierte Funktionen via export function ....

bind:this zu früh nutzen. Direkt nach dem Mount ist die Variable noch undefined, bis Svelte den DOM-Knoten erstellt hat. Im Markup oder in $effect(() => { if (player) ... }) arbeiten.

Imperative APIs überstrapazieren. Wenn bind:this für viele Methoden gebraucht wird, ist die Komponente meist falsch geschnitten. Lieber State-getrieben (isOpen-Prop) als imperativ (open()/close()).

Weiterführende Ressourcen

Externe Quellen

Verwandte Artikel

/ Weiter

Zurück zu Components

Zur Übersicht