這是〈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()用於令元件更新
