Svelte 最新中文文档翻译(9)—— bind: 模板语法

冴羽
• 阅读 53

前言

Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1

Svelte 最新中文文档翻译(9)—— bind: 模板语法

Svelte 以其独特的编译时优化机制著称,具有轻量级高性能易上手等特性,非常适合构建轻量级 Web 项目,也是我做个人项目的首选技术栈。

目前 Svelte 基于 Svelte 5 发布了最新的官方文档,但却缺少对应的中文文档。为了帮助大家学习 Svelte,为爱发电翻译了官方文档。

我同时搭建了 Svelte 最新的中文文档站点:https://svelte.yayujs.com ,如果需要辅助学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!

虽说是翻译,但个人并不喜欢严格遵守原文,为了保证中文阅读流畅,会删减部分语句,对难懂的部分也会另做补充解释,希望能给大家带来一个好的中文学习体验。

欢迎围观我的“朋友圈”、加入“低调务实优秀中国好青年”前端社群,分享技术,带你成长。

bind:

数据通常是从父级流向子级。bind: 指令允许数据反向流动,从子级流向父级。

一般语法是 bind:property={expression},其中 expression 是一个 lvalue(即一个变量或一个对象属性)。当表达式的标识符与属性同名时,我们可以省略表达式——换句话说,这两者是等价的:

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

Svelte 创建了一个事件监听器来更新绑定值。如果元素已经有一个相同事件的监听器,那个监听器会在绑定值更新之前触发。

大多数绑定是 双向的,这意味着对值的更改会影响元素,反之亦然。有一些绑定是 只读的,这意味着更改它们的值不会对元素产生影响。

函数绑定

您还可以使用 bind:property={get, set},其中 getset 是函数,允许您进行验证和转换:

<input bind:value={
    () => value,
    (v) => value = v.toLowerCase()}
/>

对于只读绑定如尺寸绑定get 值应为 null

<div
    bind:clientWidth={null, redraw}
    bind:clientHeight={null, redraw}
>...</div>

[!NOTE] 函数绑定在 Svelte 5.9.0 及更新版本中可用。

<input bind:value>

<input> 元素上使用 bind:value 指令绑定输入的 value 属性:

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

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

对于数字输入(type="number"type="range"),该值将被强制转换为数字(demo):

<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>

[!NOTE] 请谨慎使用重置按钮,并确保用户在提交表单时不会意外点击它们。

<input bind:checked>

复选框和单选输入可以绑定 bind:checked

<label>
    <input type="checkbox" bind:checked={accepted} />
    接受条款和条件
</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>

一起工作的 input 元素,比如单选框、复选框,可以使用 bind:group

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

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

<!-- 分组的单选输入是互斥的 -->
<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" />

<!-- 分组的复选框输入填充一个数组 -->
<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)" />

[!NOTE] bind:group 仅在 input 位于同一 Svelte 组件中时才有效。

<input bind:files>

<input> 元素上使用 type="file" 时,您可以使用 bind:files 获取所选文件的 FileList。当您想以编程方式更新文件时,您始终需要使用 FileList 对象。目前无法直接构造 FileList 对象,因此您需要创建一个新的 DataTransfer 对象,并从中获取 files

<script>
    let files = $state();

    function clear() {
        files = new DataTransfer().files; // null 或 undefined 无效
    }
</script>

<label for="avatar">上传图片:</label>
<input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" />
<button onclick={clear}>清空</button>

FileList 对象也不能被修改,因此如果您想从列表中删除单个文件,则需要创建一个新的 DataTransfer 对象,并添加您想保留的文件。

[!NOTE] DataTransfer 在服务器端 JavaScript 运行时可能不可用。将绑定到 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">米饭</option>
    <option value="Beans">豆子</option>
    <option value="Cheese">奶酪</option>
    <option value="Guac (extra)">鳄梨(额外)</option>
</select>

<option> 的值与其文本内容匹配时,可以省略该属性。

<select multiple bind:value={fillings}>
    <option>米饭</option>
    <option>豆子</option>
    <option>奶酪</option>
    <option>鳄梨(额外)</option>
</select>

您可以通过给 <option> 添加一个 selected 属性(如果是 <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 元素相同的所有绑定,外加只读的 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 属性的元素支持以下绑定:

[!NOTE] innerTexttextContent 之间有微妙的差异

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

尺寸

所有可见元素都有以下只读绑定,通过 ResizeObserver 测量:

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

[!NOTE] display: inline 元素没有宽度或高度(除了具有“固有”尺寸的元素,如 <img><canvas>),并且无法通过 ResizeObserver 进行观察。您需要将这些元素的 display 样式更改为其他值,例如 inline-block

bind:this

<!--- copy: false --->
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,允许您以编程方式与组件实例进行交互。

<!--- file: App.svelte --->
<ShoppingCart bind:this={cart} />

<button onclick={() => cart.empty()}> 清空购物车 </button>
<!--- file: ShoppingCart.svelte --->
<script>
    // 所有实例导出都可在实例对象上使用
    export function empty() {
        // ...
    }
</script>

bind:property for components

bind:property={variable}

您可以使用与元素相同的语法绑定组件属性。

<Keypad bind:value={pin} />

虽然 Svelte 的 props 在不绑定的情况下是响应式的,但默认情况下这种响应性只能向下流入组件。使用 bind:property 可以让组件内部对属性的更改向上传递出组件。

要将属性标记为可绑定的,请使用 $bindable 符文:

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

将属性声明为可绑定意味着它 可以 使用 bind:,但不是说它 必须 使用 bind:

可绑定属性可以有一个后备值:

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

此后备值 在属性 被绑定时适用。当属性被绑定并且存在后备值时,父级必须提供一个不同于 undefined 的值,否则会抛出运行时错误。这可以防止出现难以推理的情况,即不清楚应该应用哪个值。

Svelte 中文文档

本篇已收录在掘金专栏 《Svelte 中文文档》,该系列预计 40 篇。

系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!

此外我还写过 JavaScript 系列TypeScript 系列React 系列Next.js 系列冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog

通过文字建立交流本身就是一种缘分,欢迎围观我的“朋友圈”、加入“低调务实优秀中国好青年”前端社群,分享技术,带你成长。

点赞
收藏
评论区
推荐文章
冴羽 冴羽
4星期前
Svelte 最新中文文档翻译(1)—— 概述与入门指南
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽 冴羽
4星期前
Svelte 最新中文文档翻译(2)—— .svelte、.svelte.js 和 .svelte.ts 文件
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽 冴羽
4星期前
Svelte 最新中文文档翻译(3)—— 符文(Runes)上
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽 冴羽
4星期前
Svelte 最新中文文档翻译(4)—— 符文(Runes)下
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽 冴羽
1星期前
Svelte 最新中文文档翻译(5)—— 基础标记
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽 冴羽
1星期前
Svelte 最新中文文档翻译(6)—— if、each、key、await 逻辑区块
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽 冴羽
3天前
Svelte 最新中文文档翻译(7)—— snippet 与 @render
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽 冴羽
3天前
Svelte 最新中文文档翻译(8)—— @html、@const、@debug 模板语法
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽 冴羽
3天前
Svelte 最新中文文档翻译(10)—— use: 与 Actions
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽 冴羽
3天前
Svelte 最新中文文档翻译(11)—— 动画相关语法 transition、in、out、animate
前言Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从Svelte诞生之初,就备受开发者的喜爱,根据统计,从2019年到2024年,连续6年一直是开发者最感兴趣的前端框架No.1:Svelte以其独特的编译时优化机制著称,具有轻量级、高性能、易上
冴羽
冴羽
Lv1
男 · 淘宝 · 前端工程师
分享技术,也分享人生。GitHub 中国区 Top 30,掘金签约作者,掘金前端领域关注数 Top 1。至今写过 14 个系列、几百篇技术文章,全网千万阅读。
文章
45
粉丝
16
获赞
67