Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mqyqingfeng opened this issue Feb 15, 2025 · 0 comments
Open

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

mqyqingfeng opened this issue Feb 15, 2025 · 0 comments

Comments

@mqyqingfeng
Copy link
Owner

前言

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

image.png

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant