通常,Svelte 中的数据流是 自上而下,父组件可以在子组件上设置 props, 子组件向父组件通信,也是需要借助父组件传递给子组件的方法来完成,但是在某些情况下,需要打破这种规则,尤其是在使用表单元素来接收用户数据的时候
<script>
let name = 'world';
</script>
<!-- 加上bind指令后 更改name的值时会更新 input 的值,反之亦然 --- 双向绑定 -->
<!--
如果不使用bind指令
需要其添加对应的事件处理程序(这里是 on:input ),
在该程序中将 name 的值设置为 event.target.value
但是表单元素一般不止一个
这么写意味着很繁琐,可以认为bind是上述操作的语法糖
-->
<input bind:value={name}>
<h1>Hello {name}!</h1>
表单元素的绑定
文本输入框 input[type=text]
<script>
let name = 'world';
</script>
<input bind:value={name}>
<h1>Hello {name}!</h1>
数字或范围输入框 input[type=number|range]
<!-- 表单中获取的值都是字符串,一般都需要手动进行转换,但是Svelte不需要, Svelte会帮组我们进行转换 -->
<input type=number value={a} min=0 max=10>
<input type=range bind:value={a} min=0 max=10>
复选框 input[type=checkbox]
<input type=checkbox bind:checked={yes}>
输入框组 radio & checkbox
有多个输入框需要关联到同一个值的时候,则可以将bind:group与value属性一起使用。同一组的单选框(Radio)之间是互斥的;而同一组复选框中被选中的值会汇集到一个数组中
<!-- bind:group --- 分组 --- 同一名称为一组 值为value中对应的值 -->
<label><input type=radio bind:group={scoops} value={1}>One scoop</label>
<label><input type=radio bind:group={scoops} value={2}>Two scoops</label>
<label><input type=radio bind:group={scoops} value={3}>Three scoops</label>
<!-- 多选框组 会被绑定成一个数组 -->
<input type=checkbox bind:group={flavours} name="flavours" value="Cookies"> Cookies
<input type=checkbox bind:group={flavours} name="flavours" value="Mint"> Mint
<input type=checkbox bind:group={flavours} name="flavours" value="Raspberry"> Raspberry
多行纯文本 textarea
<textarea bind:value={value}></textarea>
<!-- 属性名和属性值同名可以简写(适用于所有的双向绑定) -->
<textarea bind:value></textarea>
选择框 select(单选)
<script>
let questions = [
{ id: 1, text: `Where did you go to school?` },
{ id: 2, text: `What is your mother's name?` }
];
// 如果绑定的值没有设置初始值,那么默认值就是列表中的第一项,即questions[0]
let selected;
</script>
<!-- bind:value 是添加在select上的 -->
<select bind:value={selected} on:blur="{() => answer = ''}">
{#each questions as question}
<!-- 在svelte中,option上绑定的值可以是一个对象 -->
<option value={question}>
{question.text}
</option>
{/each}
</select>
<!-- 因为并没有给selected设置初始值,所以selected可能为空,所以此时需要进行判断 -->
<p>selected question {selected ? selected.id : '[waiting...]'}</p>
选择框 select(多选)
<h2>Flavours</h2>
<!-- 此时flavours是一个数组,而非一个普通的值 -->
<select multiple bind:value={flavours}>
{#each menu as flavour}
<option value={flavour}>{flavour}</option>
{/each}
</select>
可编辑属性 contenteditable
<!-- 给元素加上 contenteditalbe 属性,元素即可获得可编辑能力 -->
<!-- 具有contenteditable="true"属性的元素都支持绑定textContent和innerHTML -->
<div
contenteditable="true"
bind:innerHTML={html}
></div>
在 each 块中绑定
<!-- 在 Svelte 中,可以在each块中绑定属性 -->
{#each todos as todo}
<div class:done={todo.done}>
<input type=checkbox bind:checked={todo.done}>
<input placeholder="What needs to be done?" bind:value={todo.text}>
</div>
{/each}
特殊的绑定
尺寸绑定
- 每个块级元素都可以绑定到
clientWidth、clientHeight、offsetWidth以及offsetHeight - 这些绑定都是只读的,修改
w或h的值不会有任何效果 - 使用这类测量技术,会涉及到一些额外开销,因此不建议在大量元素上使用。
display: inline的内联元素是不能测量的,没有子级的元素也不能(例如<canvas>),这种情况,你需要测量的是包裹它的外层元素。
<div bind:clientWidth={w} bind:clientHeight={h}>
<span style="font-size: {size}px">{text}</span>
</div>
媒体相关元素 audio & video
<audio>和<video>元素具有一些可以绑定的属性。具体可以点击参看示例代码
this
- 绑定 this 与 Vue 的 ref 功能相似,都是为了取得当前组件的实际 DOM 对象
this绑定适用于任意元素或组件,允许你获取渲染的元素的引用this绑定获取的值是只读的- 组件 mounted 之前,所有对于DOM的操作都是无效的,对使用this获取的dom元素的操作应放在
onMount这个生命周期函数中
<span bind:this={spanElem}>Hello Svelte</span>
<script>
import { onMount } from 'svelte';
let spanElem;
onMount(() => console.log(spanElem))
</script>
组件绑定
在Svelte中,组件绑定 类似于 vue中的 .sync操作符
<!-- 父组件 -->
<script>
let pin = ''
</script>
<!-- 使用bind:xxx 后,在父组件中,pin值一旦发生了改变,子组件的value值也会发生改变 -->
<Keypad bind:value={pin} on:submit={handleSubmit}/>
<!----------------------------------------------------------------->
<!-- 子组件 -->
<script>
export let value = '';
// 使用bind:xxx 后,在子组件中,修改了value值,父组件中的pin也会相应发生改变
const select = num => () => value += num;
</script>
<button on:click="{select(1)}">+1</button>
组件绑定需要谨慎小心。如果你的 App 中数据过多,尤其是在没有 “单一数据源” 的情况下,
可能难以跟踪 App 相关的数据流,因此此时在子组件中修改了值,直接影响外部提供的状态
<!-- 父组件 App.svelte -->
<script>
import Keypad from './Keypad.svelte'
let pin = ''
$: console.log('pin', pin)
</script>
<Keypad bind:value={pin} />
<!----------------------------------------------------------------->
<!-- 中间组件 Keypad.svelte -->
<script>
export let value = ''
import Cpn from './Cpn.svelte'
</script>
<Cpn bind:value />
<!----------------------------------------------------------------->
<!-- 子组件 Cpn.svelte -->
<script>
export let value = '';
const select = num => () => value += num;
$: console.log('value', value)
</script>
<button on:click="{select(1)}">+1</button>