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
并且是表单的一部分,则在表单重置时,它将恢复为该值而不是空字符串。请注意,对于初始渲染,绑定的值优先,除非它是 null
或 undefined
。
<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
。请注意,对于初始渲染,绑定的值优先,除非它是 null
或 undefined
。
<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>
您可以通过向应最初选中的 <option>
(或在 <select multiple>
的情况下为选项)添加 selected
属性来为 <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] 元素相同的所有绑定,以及只读的 videoWidth
和 videoHeight
绑定。
<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
属性的元素支持以下绑定
<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
——换句话说,您应该在 effect 或事件处理程序内读取它,而不是在组件初始化期间
<script>
/** @type {HTMLCanvasElement} */
let canvas;
$effect(() => {
const ctx = canvas.getContext('2d');
drawStuff(ctx);
});
</script>
<canvas bind:this={canvas} />
组件也支持 bind:this
,允许您以编程方式与组件实例交互。
<ShoppingCart bind:this={cart} />
<button onclick={() => cart.empty()}> Empty shopping cart </button>
<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
,否则会抛出运行时错误。这可以防止难以理解的情况,在这些情况下不清楚应应用哪个值。