Svelte中的双向数据绑定和生命周期
时间:2021-03-24 14:30:46
双向数据绑定
在Svelte
中数据流是自上而下的,即单项数据流(父组件可以将数据通过prop
传递给子组件,但是子组件不能直接修改prop
影响父组件的值,一般可通过事件传递给父组件,然后父组件在捕获事件并在事件中修改其值)。但是在Svelte
中提供了bind:value
指令可以实现双向数据流,就像Vue
中的v-model
。
Input
input
不同类型实现双向数据流的方式:
- 输入框(
text/password/number
)、文本域(textarea
):bind:value
- 单选框(
radio
):可以通过bind:group
来绑定指定当前选中值,通过value
来指定值。 - 多选框(
checkbox
):可以通过bind:group
来绑定指定当前选中值,通过value
来指定值,也可通过bind:checked
来控制单个多选框状态。
<script>
let value = '';
let textareaValue = '';
let step = 0;
let checked = false;
let radio = '1';
let checkboxGroup = ['1'];
</script>
<h3>{value}</h3>
<input bind:value />
<br />
<h3>{textareaValue}</h3>
<textarea bind:value={textareaValue} />
<br />
<input type="number" bind:value={step} />
<br />
<input type="range" bind:value={step} />
<br />
radio:{radio}
<label>选项1<input type="radio" bind:group={radio} value="1" /></label>
<label>选项2<input type="radio" bind:group={radio} value="2" /></label>
<label>选项3<input type="radio" bind:group={radio} value="3" /></label>
<br />
checked:{checked}
<input type="checkbox" bind:checked />
<br />
checkboxGroup:{checkboxGroup}
<label>选项1<input type="checkbox" bind:group={checkboxGroup} value="1" /></label>
<label>选项2<input type="checkbox" bind:group={checkboxGroup} value="2" /></label>
<label>选项3<input type="checkbox" bind:group={checkboxGroup} value="3" /></label>
Select
select
通过bind:value
来实现双向数据流,注意如果没有设置初始值的话,则默认为第一个,如果多选可以设置属性multiple
。
<script>
let value = '';
let valueGroup = [];
</script>
<h3>value:{value}</h3>
<select bind:value>
<option value="1">选项1</option>
<option value="2">选项2</option>
<option value="3">选项3</option>
<option value="4">选项4</option>
</select>
<h3>valueGroup: {valueGroup}</h3>
<select multiple bind:value={valueGroup}>
<option value="1">选项1</option>
<option value="2">选项2</option>
<option value="3">选项3</option>
<option value="4">选项4</option>
</select>
可编辑元素
当元素设置属性contenteditable="true"
时,元素就变成了一个可修改的元素了。可通过bind:innerHTML
来实现双向数据流。
<script>
let html = '<p>内容</p>';
</script>
<h3>
html: {html}
</h3>
<div class="html" contenteditable="true" bind:innerHTML={html} />
<style>
.html {
border: 1px solid #000;
}
</style>
Audio、Video
Audio
和Video
中有一些属性是只读的,不能实现双向绑定:duration
、buffered
、seekable
、played
、seeking
、ended
。可双向数据绑定:currentTime
、playbackRate
、paused
、volume
、muted
块级元素
块级元素的这些属性可以实现双向数据绑定:clientWidth
、clientHeight
、offsetWidth
、offsetHeight
this
如果想访问 DOM 元素,就像Vue
中的ref
那样,可以通过bind:this
,注意:bind:this
需要在生命周期函数onMount
中才能获取到。
<script>
import { onMount } from 'svelte';
let input;
onMount(() => {
console.log(input);
});
</script>
<input type="text" bind:this={input} />
组件的双向数据
组件的双向数据绑定也可通过bind:value
来实现。
Input.svelte
<script>
export let value;
</script>
<input bind:value />
App.svelte
<script>
import Input from './Input.svelte';
let value = '';
</script>
<div>value:{value}</div>
<Input bind:value />
生命周期
在Svelte
主要有一下几个生命周期:
script
:在script
标签中的代码都会在创建前运行。onMount
:当组件创建完成首次渲染 DOM 后触发此生命周期。如果在此生命周期中返回一个函数,则在销毁组件时调用。beforeUpdate
:当组件状态发生变化且在 DOM 更新前会触发此生命周期。afterUpdate
:当组件状态发生变化且 DOM 更新后会触发此生命周期。onDestroy
:当组件销毁时触发此生命周期。
其中,还有一个tick
函数,此函数的作用相当于Vue
中的nextTick
。当组件状态发生改变不会立即更新 DOM,如果想在更新组件状态后获取最新 DOM 可以使用tick
。
<script>
import { onMount, beforeUpdate, afterUpdate, onDestroy, tick } from 'svelte';
let name = 'world';
let h;
console.log('创建前');
onMount(() => {
console.log('onMount');
return () => {
console.log('onMount return function');
};
});
beforeUpdate(() => {
console.log('beforeUpdate:', h?.innerText);
});
afterUpdate(() => {
console.log('afterUpdate:', h?.innerText);
});
onDestroy(() => {
console.log('onDestroy');
});
const onClick = async () => {
name = 'Svelte';
console.log('onClick:', h?.innerText);
await tick();
console.log('onClick tick:', h?.innerText);
};
</script>
<h1 bind:this={h} on:click={onClick}>Hello {name}!</h1>