Skip to main content
基本 Svelte
介绍
反应性
属性
逻辑
事件
绑定
类和样式
动作
转换
高级 Svelte
高级反应性
重用内容
运动
高级绑定
高级转换
上下文 API
特殊元素
<script module>
后续步骤
基本 SvelteKit
介绍
路由
加载数据
标题和 cookie
共享模块
表单
API 路由
$app/state
错误和重定向
高级 SvelteKit
钩子
页面选项
链接选项
高级路由
高级加载
环境变量
结论

到目前为止,我们已经讨论了状态方面的反应性。但这只是等式的一半 - 状态只有在某些东西对其做出反应时才会产生反应,否则它只是一个闪闪发光的变量。

¥So far we’ve talked about reactivity in terms of state. But that’s only half of the equation — state is only reactive if something is reacting to it, otherwise it’s just a sparkling variable.

做出反应的东西称为效果。你已经遇到了效果 - Svelte 代表你创建的效果,用于响应状态更改来更新 DOM - 但你也可以使用 $effect 符文创建自己的效果。

¥The thing that reacts is called an effect. You’ve already encountered effects — the ones that Svelte creates on your behalf to update the DOM in response to state changes — but you can also create your own with the $effect rune.

大多数情况下,你不应该这样做。$effect 最好被视为应急方案,而不是经常使用的东西。例如,如果你可以将副作用放在 事件处理程序 中,这几乎总是更好的选择。

¥[!NOTE] Most of the time, you shouldn’t. $effect is best thought of as an escape hatch, rather than something to use frequently. If you can put your side effects in an event handler, for example, that’s almost always preferable.

假设我们想使用 setInterval 来跟踪组件的安装时间。创建效果:

¥Let’s say we want to use setInterval to keep track of how long the component has been mounted. Create the effect:

App
<script>
	let elapsed = $state(0);
	let interval = $state(1000);

	$effect(() => {
		setInterval(() => {
			elapsed += 1;
		}, interval);
	});
</script>
<script lang="ts">
	let elapsed = $state(0);
	let interval = $state(1000);

	$effect(() => {
		setInterval(() => {
			elapsed += 1;
		}, interval);
	});
</script>

单击 ‘加速’ 按钮几次,注意 elapsed 的上升速度更快,因为每次 interval 变小时,我们都会调用 setInterval

¥Click the ‘speed up’ button a few times and notice that elapsed ticks up faster, because we’re calling setInterval each time interval gets smaller.

如果我们然后单击 ‘减速’ 按钮...嗯,它不起作用。这是因为我们在效果更新时没有清除旧间隔。我们可以通过返回清理函数来解决这个问题:

¥If we then click the ‘slow down’ button... well, it doesn’t work. That’s because we’re not clearing out the old intervals when the effect updates. We can fix that by returning a cleanup function:

App
$effect(() => {
	const id = setInterval(() => {
		elapsed += 1;
	}, interval);

	return () => {
		clearInterval(id);
	};
});

interval 更改时,以及当组件被销毁时,在效果函数重新运行之前立即调用清理函数。

¥The cleanup function is called immediately before the effect function re-runs when interval changes, and also when the component is destroyed.

如果效果函数在运行时没有读取任何状态,它将只在组件挂载时运行一次。

¥If the effect function doesn’t read any state when it runs, it will only run once, when the component mounts.

效果不会在服务器端渲染期间运行。

¥[!NOTE] Effects do not run during server-side rendering.

上一页 下一页
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>