跳至主要內容

bind

資料通常是從父元件向下流向子元件。 bind: 指令允許資料反向流動,從子元件流向父元件。

一般語法為 bind:property={expression},其中 expression 是一個左值(即變數或物件屬性)。當表達式是一個與屬性名稱相同的識別符號時,我們可以省略表達式 — 換句話說,它們是等價的。

<input bind:value={value} />
<input bind:value />

Svelte 會建立一個事件監聽器來更新綁定的值。如果元素已經有一個相同事件的監聽器,則該監聽器會在綁定值更新之前觸發。

大多數綁定都是雙向的,這表示對值的變更會影響元素,反之亦然。少數綁定是唯讀的,這表示變更它們的值不會對元素產生任何影響。

<input bind:value>

<input> 元素上的 bind:value 指令會綁定輸入的 value 屬性

<script>
	let message = $state('hello');
</script>

<input bind:value={message} />
<p>{message}</p>

如果是數值輸入(type="number"type="range"),則該值會被強制轉換為數字 (範例)

<script>
	let a = $state(1);
	let b = $state(2);
</script>

<label>
	<input type="number" bind:value={a} min="0" max="10" />
	<input type="range" bind:value={a} min="0" max="10" />
</label>

<label>
	<input type="number" bind:value={b} min="0" max="10" />
	<input type="range" bind:value={b} min="0" max="10" />
</label>

<p>{a} + {b} = {a + b}</p>

如果輸入為空或無效(在 type="number" 的情況下),則值為 undefined

從 5.6.0 版本開始,如果 <input> 具有 defaultValue 並且是表單的一部分,則當表單重設時,它會還原為該值,而不是空字串。請注意,對於初始渲染,綁定的值優先,除非它是 nullundefined

<script>
	let value = $state('');
</script>

<form>
	<input bind:value defaultValue="not the empty string">
	<input type="reset" value="Reset">
</form>

請謹慎使用重設按鈕,並確保使用者不會在嘗試提交表單時不小心點擊它們。

<input bind:checked>

可以使用 bind:checked 綁定核取方塊和單選按鈕輸入

<label>
	<input type="checkbox" bind:checked={accepted} />
	Accept terms and conditions
</label>

從 5.6.0 版本開始,如果 <input> 具有 defaultChecked 屬性並且是表單的一部分,則當表單重設時,它會還原為該值,而不是 false。請注意,對於初始渲染,綁定的值優先,除非它是 nullundefined

<script>
	let checked = $state(true);
</script>

<form>
	<input type="checkbox" bind:checked defaultChecked={true}>
	<input type="reset" value="Reset">
</form>

<input bind:group>

一起運作的輸入可以使用 bind:group

<script>
	let tortilla = $state('Plain');

	/** @type {Array<string>} */
	let fillings = $state([]);
</script>

<!-- grouped radio inputs are mutually exclusive -->
<input type="radio" bind:group={tortilla} value="Plain" />
<input type="radio" bind:group={tortilla} value="Whole wheat" />
<input type="radio" bind:group={tortilla} value="Spinach" />

<!-- grouped checkbox inputs populate an array -->
<input type="checkbox" bind:group={fillings} value="Rice" />
<input type="checkbox" bind:group={fillings} value="Beans" />
<input type="checkbox" bind:group={fillings} value="Cheese" />
<input type="checkbox" bind:group={fillings} value="Guac (extra)" />

bind:group 僅在輸入位於同一個 Svelte 元件中時才有效。

<input bind:files>

在具有 type="file"<input> 元素上,您可以使用 bind:files 來取得選取檔案的 FileList。當您想要以程式方式更新檔案時,您始終需要使用 FileList 物件。目前無法直接建構 FileList 物件,因此您需要建立新的DataTransfer 物件並從那裡取得 files

<script>
	let files = $state();

	function clear() {
		files = new DataTransfer().files; // null or undefined does not work
	}
</script>

<label for="avatar">Upload a picture:</label>
<input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" />
<button onclick={clear}>clear</button>

FileList 物件也無法修改,因此如果您想從清單中刪除單個檔案,則需要建立新的 DataTransfer 物件並新增您要保留的檔案。

DataTransfer 可能在伺服器端 JS 執行階段不可用。將綁定到 files 的狀態保持未初始化,可以防止在伺服器端渲染元件時出現潛在錯誤。

<select bind:value>

<select> 的值綁定對應於選取的 <option> 上的 value 屬性,它可以是任何值(不僅僅是字串,這在 DOM 中通常是這種情況)。

<select bind:value={selected}>
	<option value={a}>a</option>
	<option value={b}>b</option>
	<option value={c}>c</option>
</select>

<select multiple> 元素的行為類似於核取方塊群組。綁定的變數是一個陣列,其項目對應於每個選取的 <option>value 屬性。

<select multiple bind:value={fillings}>
	<option value="Rice">Rice</option>
	<option value="Beans">Beans</option>
	<option value="Cheese">Cheese</option>
	<option value="Guac (extra)">Guac (extra)</option>
</select>

<option> 的值與其文字內容相符時,可以省略該屬性。

<select multiple bind:value={fillings}>
	<option>Rice</option>
	<option>Beans</option>
	<option>Cheese</option>
	<option>Guac (extra)</option>
</select>

您可以透過將 selected 屬性新增至最初應該選取的 <option>(或在 <select multiple> 的情況下新增至選項),為 <select> 指定預設值。如果 <select> 是表單的一部分,則當表單重設時,它會還原為該選取。請注意,對於初始渲染,如果綁定的值不是 undefined,則它會優先。

<select bind:value={selected}>
	<option value={a}>a</option>
	<option value={b} selected>b</option>
	<option value={c}>c</option>
</select>

<audio>

<audio> 元素有自己的一組綁定 — 五個雙向綁定...

...和七個唯讀綁定

<audio src={clip} bind:duration bind:currentTime bind:paused></audio>

<video>

<video> 元素具有與 [#audio] 元素相同的所有綁定,外加唯讀的 videoWidthvideoHeight 綁定。

<img>

<img> 元素有兩個唯讀綁定

<details bind:open>

<details> 元素支援綁定到 open 屬性。

<details bind:open={isOpen}>
	<summary>How do you comfort a JavaScript bug?</summary>
	<p>You console it.</p>
</details>

contenteditable 綁定

具有 contenteditable 屬性的元素支援以下綁定

innerTexttextContent 之間存在細微差異

<div contenteditable="true" bind:innerHTML={html} />

尺寸

所有可見元素都有以下唯讀綁定,這些綁定使用 ResizeObserver 測量

<div bind:offsetWidth={width} bind:offsetHeight={height}>
	<Chart {width} {height} />
</div>

display: inline 元素沒有寬度或高度(除了具有「固有」尺寸的元素,例如 <img><canvas>),並且無法使用 ResizeObserver 觀察。您需要將這些元素的 display 樣式變更為其他樣式,例如 inline-block

bind:this

bind:this={dom_node}

要取得 DOM 節點的參照,請使用 bind:this。在元件掛載之前,該值將為 undefined — 換句話說,您應該在效果或事件處理常式內部讀取它,而不是在元件初始化期間讀取。

<script>
	/** @type {HTMLCanvasElement} */
	let canvas;

	$effect(() => {
		const ctx = canvas.getContext('2d');
		drawStuff(ctx);
	});
</script>

<canvas bind:this={canvas} />

元件也支援 bind:this,允許您以程式方式與元件實例互動。

App
<ShoppingCart bind:this={cart} />

<button onclick={() => cart.empty()}> Empty shopping cart </button>
ShoppingCart
<script>
	// All instance exports are available on the instance object
	export function empty() {
		// ...
	}
</script>

元件的 bind:property

bind:property={variable}

您可以使用與元素相同的語法來綁定元件屬性。

<Keypad bind:value={pin} />

雖然 Svelte 屬性在沒有綁定的情況下也是響應式的,但該響應性預設只向下流動到元件中。使用 bind:property 允許從元件內部對屬性進行的變更向上流出元件。

要將屬性標記為可綁定,請使用 $bindable 符文。

<script>
	let { readonlyProperty, bindableProperty = $bindable() } = $props();
</script>

將屬性宣告為可綁定表示它可以透過 bind: 使用,而不是必須透過 bind: 使用。

可綁定屬性可以有回退值

<script>
	let { bindableProperty = $bindable('fallback value') } = $props();
</script>

此回退值在屬性綁定時適用。當屬性已綁定且存在回退值時,父元件預期提供一個不是 undefined 的值,否則會擲回執行階段錯誤。這可以防止難以理解的情況,在這種情況下,不清楚應該套用哪個值。

在 GitHub 上編輯此頁面

上一個 下一個