到目前为止,我们已经从状态的角度讨论了响应式。但这只是等式的一半——只有当某些东西对状态做出反应时,状态才是响应式的,否则它只是一个闪闪发光的变量。
做出反应的事物称为副作用。你已经遇到过副作用了——Svelte 代表你创建的那些副作用,用于响应状态更改更新 DOM——但你也可以使用 $effect
符文创建自己的副作用。
大多数时候,你不应该这样做。
$effect
最好被视为一个逃生舱口,而不是经常使用的东西。例如,如果你可以将你的副作用放在事件处理程序中,这几乎总是更好的选择。
假设我们想使用 setInterval
来跟踪组件已挂载多长时间。创建副作用
应用
<script>
let elapsed = $state(0);
let interval = $state(1000);
$effect(() => {
setInterval(() => {
elapsed += 1;
}, interval);
});
</script>
点击“加速”按钮几次,注意 elapsed
计数更快,因为我们每次 interval
变小都会调用 setInterval
。
如果我们然后点击“减速”按钮……好吧,它不起作用。这是因为当副作用更新时,我们没有清除旧的间隔。我们可以通过返回一个清理函数来修复它
应用
$effect(() => {
const id = setInterval(() => {
elapsed += 1;
}, interval);
return () => {
clearInterval(id);
};
});
清理函数在 interval
更改时副作用函数重新运行之前立即调用,以及在组件销毁时调用。
如果副作用函数在运行时不读取任何状态,它只会运行一次,即组件挂载时。
副作用在服务器端渲染期间不会运行。
1
2
3
4
5
6
7
8
9
10
<script>
let elapsed = $state(0);
let interval = $state(1000);
</script>
<button onclick={() => interval /= 2}>speed up</button>
<button onclick={() => interval *= 2}>slow down</button>
<p>elapsed: {elapsed}</p>