這是〈Svelte 從小白到入門〉系列的第五集,各集連結如下:
- 〈Svelte 從小白到入門(一)元件、事件、Reactivity〉
- 〈Svelte 從小白到入門(二)Props、邏輯、迴圈、Await〉
- 〈Svelte 從小白到入門(三)事件〉
- 〈Svelte 從小白到入門(四)數據綁定〉
- 〈Svelte 從小白到入門(五)生命週期〉
- 〈Svelte 從小白到入門(六)Store〉
- 〈Svelte 從小白到入門(七)動態效果〉
- 〈Svelte 從小白到入門(八)進出場效果〉
- 〈Svelte 從小白到入門(九)動畫效果〉
- 〈Svelte 從小白到入門(十)Action〉
- 〈Svelte 從小白到入門(十一)CSS Class〉
- 〈Svelte 從小白到入門(十二)Slot〉
- 〈Svelte 從小白到入門(十三)Context〉
- 〈Svelte 從小白到入門(十四)Svelte 的特殊元素〉
- 〈Svelte 從小白到入門(十五)Module Context〉
- 〈Svelte 從小白到入門(十六)Debugging〉
- 〈Svelte 從小白到入門(十七)結束與展望〉
本週末是台灣國慶連假,封面圖特別改用今年國慶的視覺主題「金陽雙十」的編織圖案,祝台灣生日快樂,也感謝這個自由的國度讓我們擁有免於被囚禁在網路長城內的自由。
生命週期
所謂的生命週期,指的是一個 Svelte 元件從被創建到被銷毀之間的幾個關鍵時機點,其中的 onMount
的時機點為元件被瀏覽器 render 出來後的那一刻。
onMount
在上一集的 canvas 範例裡,有出現過 onMount()
的函式,當時我們做的是把 <canvas>
元素綁定到 JS 的 canvas
變數上,並利用 Canvas API 撰寫它的一些動態效果,因為必須調用到瀏覽器提供的 Canvas API,就必然得等到 <canvas>
被瀏覽器 render 後才能正確調用,又或者是某些行為必許操作元件內的其他元素,也必須等待瀏覽器把元件都 render 後才可以操作,因此我們才把那些動態效果的敘述放在 onMount()
裡面。
下面的這個例子,我們在 onMount()
裡面用 fetch()
去抓外部 API 的用戶頭像,並顯示出來:
在 onMount()
內的程式碼,不會在 SSR 階段被執行,而像 fetch()
這個通常用於抓取動態內容的函式也不適合在 SSR 執行,因此放在 onMount()
內也算是適得其所。
另外注意到,在第二集曾經提過的 {#each}
迴圈也可以用 {:else}
,當 photos
陣列還未生成時,可以用 {:else}
顯示佔位圖或提示文字。
onDestroy
onMount
會在 Svelte 元件在瀏覽器被 render 時執行,onDestroy
則是會在元件被銷毀時執行。
在下面的例子裡,父元件 App 有一個 Timer 子元件,以及一個能切換 Timer 存在與否的按鈕。
Timer 是個以 setInterval()
函式建構的計時器,透過 App 給 Timer 的 callback 函式 handleTick
,計時器會把 App 的累積秒數 seconds
持續隨讀秒的頻率加一加一加一,而一旦用戶按下「Close Timer」,App 內的 Timer 元件隨之銷毀,並觸發 Timer 內的 onDestroy()
,其內的 clearInterval()
被執行,令原本的 timer
失效。
看文字敘述好像很複雜,實際上真的很複雜…:
beforeUpdate & afterUpdate
元件被更新的前後,也有相對應的生命週期函式可以調用。
顧名思義,beforeUpdate
會在元件更新前調用、afterUpdate
則會在元件更新後調用。
下面這個對話範例,我們希望隨著對話的增加,畫面自動幫用戶捲動到最下方:
範例中,往來的對話內容都放在 JS 的 comments
,當用戶送出文字後,對話框綁定的 handleKeydown()
負責更新 comments
的內容,此時就會觸發 beforeUpdate()
與 afterUpdate()
,beforeUpdate()
用於判斷是否要自動捲動到最底,如果要捲動,則令 autoscroll
為 true
,而 afterUpdate()
的內容就相當單純了,呼叫 scrollTo()
捲動到最下面。
要特別注意的是,元件在初始化時,onMount
之前,也會觸發 beforeUpdate
,因此我們在 beforeUpdate()
函式內有著 autoscroll = div
的敘述,這裡的「div
」變數會是 undefined
,轉換成 boolean 會是 false
,也就是 autoscroll = false
,直到瀏覽器把元件 render 後,JS 的 div
才會與 HTML 中的 div.scrollable
綁定,綁定後的 autoscroll
才有可能變為 true
。
tick
在某些情況下,出於效能的考量,Svelte 並不會立即更新元件狀態,此時我們可以呼叫 tick()
使元件更新狀態。
下面的例子裡,選取一段文字,按下 TAB,選取文字會轉為大寫,在瀏覽器的預設行為下,游標會跳到最末,而我們的程式碼想令游標保持原本選取的區段,因此引入 tick()
令元件更新,並執行保留選取區段的程式碼:
小結
本集重點整理:
onMount
發生於 Svelte 元件被瀏覽器 render 之時fetch()
函式一般用於抓取屬於特定用戶的專屬內容,建議放在onMount()
內執行{#each}
迴圈也可以用{:else}
用於顯示陣列元素未生成時的內容onDestroy
發生於 Svelte 元件被銷毀之時beforeUpdate
發生於 Svelte 元件更新前afterUpdate
發生於 Svelte 元件更新後tick()
用於令元件更新