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:
<script>
let { value = $bindable(0) } = $props();
</script>
<input type="number" bind:value />Im Eltern wird die Two-Way-Variante mit bind:value={...} genutzt:
<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:
<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:
<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:
<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><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:
<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:
<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
<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><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:
<!-- 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()).