到目前為止,我們已經從狀態的角度討論了響應性。但這只是等式的一半 —— 只有當有東西對其「響應」時,狀態才是響應式的,否則它只是一個閃閃發光的變數。
響應的事物稱為「效果」。你已經遇到過效果了 —— Svelte 代表你建立的效果,用於響應狀態更改更新 DOM —— 但你也可以使用 $effect
rune 建立自己的效果。
大多數情況下,你不應該這麼做。
$effect
最好被視為一種逃生通道,而不是頻繁使用的東西。例如,如果你可以將副作用放在事件處理器中,那幾乎總是更可取的。
假設我們想要使用 setInterval
來追蹤元件已掛載的時間。建立效果
App
<script>
let elapsed = $state(0);
let interval = $state(1000);
$effect(() => {
setInterval(() => {
elapsed += 1;
}, interval);
});
</script>
多次點擊「加速」按鈕,並注意 elapsed
滴答聲更快,因為每次 interval
變小時我們都會呼叫 setInterval
。
如果我們接著點擊「減速」按鈕...嗯,它不起作用。那是因為當效果更新時,我們沒有清除舊的間隔。我們可以透過傳回一個清理函式來修正這個問題
App
$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>