Svelte 生命週期

tags: Svelte
category: Front-End
description: Svelte 生命週期
created_at: 2023/04/04 23:00:00

cover image


回到 手把手開始寫 Svelte


前言

Svelte 提供的生命週期相對來說比較少,不像是 Vue 3 有一大張圖,有興趣可以去看。

但也相對的比較簡單一些,主要就以下四個

  • onMount
  • onDestroy
  • beforeUpdate
  • afterUpdate

還有一個 tick() 函數


onMount & onDestroy

最簡單的生命週期,只會在頁面 mount(掛上去DOM) 時觸發

<script lang="ts">
    import { onMount } from 'svelte';

    onMount(() => {
        console.log('mount page');
    });
</script>

而對應到的就是 onDestroy,就是當他從DOM被拔掉(unmount)時觸發

直接拿 Child.svelte 當範例

<script lang="ts">
    import { onDestroy, onMount } from 'svelte';

    onMount(() => {
        console.log('mount child');
    });

    onDestroy(() => {
        console.log('destroy child');
    });
</script>

<div>Child</div>

然後像這樣子使用他

<script lang="ts">
    import Child from '../components/Child.svelte';

    let num = 0;
</script>

<button on:click={() => num++}>num++</button>
{#if num % 2 == 0}
    <Child />
{/if}

可以嘗試點按鈕,然後觀察 console 的變化。


beforeUpdate & afterUpdate

  • beforeUpdate: 在 DOM 更新之前觸發
  • afterUpdate: 在 DOM 與資料同步後觸發
<script lang="ts">
    import { afterUpdate, beforeUpdate } from 'svelte';

    beforeUpdate(() => {
        console.log('beforeUpdate');
    });

    afterUpdate(() => {
        console.log('afterUpdate');
    });

    let num = 0;
</script>

<button on:click={() => num++}>num++</button>
{num}

並不是說畫面有更新才會觸發,也就是你把 {num} 拿掉,還是會觸發。

因為他只是個生命週期,他一直在循環在運作,只是用上面這樣解釋比較簡單。

其實有點像下面這樣(模擬而已):

updateVariable()
beforeUpdate()
updateDOM()
afterUpdate()

也就是說你在 beforeUpdate 拿的到新的變數,但會拿到舊的 DOM

afterUpdate 就都會拿到新的。


tick 函數

這個可能會比較需要想像一些,還記得在Svelte 響應式資料之$這一篇有提到一個問題

    <script>
    let count = 0;
    $: doubleCount = count * 2;
    const update = () => {
        count += 1;
        console.log(count, doubleCount);
    };
</script>

<div>count: {count}</div>
<div>doubleCount: {doubleCount}</div>
<button on:click={update}>count++</button>

然後提到說 console.log 的值會錯,當時提到的解法是把 $ 拉出去,如下

    let count = 0;
    $: doubleCount = count * 2;
    const update = () => {
        count += 1;
    };
    $: console.log(count, doubleCount);

還有一個解法,就是使用 tick(),如下

<script>
    import { tick } from 'svelte';

    let count = 0;
    $: doubleCount = count * 2;
    const update = async () => {
        count += 1;
        await tick();
        console.log(count, doubleCount);
    };
</script>

<div>count: {count}</div>
<div>doubleCount: {doubleCount}</div>
<button on:click={update}>count++</button>

tick() 會回傳一個 Promise,他會在你的 state 被更新到 DOM 完之後被 resolve(如果有需要更新的話,不然他會立刻被 resolve)

也可以看下面的範例更好理解

<script>
    let count = 0;
    const update = async () => {
        count += 1;
        count += 1;
        count += 1;
    };

    $: console.log('count', count);
</script>

<button on:click={update}>count++</button>

這樣子當你按一下按鈕,count會被增加 3 且只 console 出一次。

如果你希望可以三次都 console 出來,則可以在中間加入 tick()

    import { tick } from 'svelte';

    let count = 0;
    const update = async () => {
        count += 1;
        await tick();
        count += 1;
        await tick();
        count += 1;
    };



最後更新時間: 2023年04月04日.