EP11 - 生命週期鉤子

閱讀時間約 1 分鐘
Lifecycle Hooks,感覺蠻有趣~生命週期有哪些狀態?
照理說應該會看到一個流程圖的樣子~
對於生命週期都會覺得比較常用通常是某幾個階段~
我只想要Destroy這個生命週期~www

每個 Vue 組件實例在創建時會經歷一系列的初始化步驟例。例如,它需要設置數據觀測編譯模板將實例掛載到 DOM 上,並在數據變更時更新 DOM。在這些過程中,它會執行稱為生命週期鉤子函數,這些鉤子允許用戶在特定階段插入自己的代碼。

註冊生命週期鉤子 - Registering Lifecycle Hooks

例如,onMounted 鉤子可以在組件完成初始渲染並創建 DOM 節點後運行代碼:

<script setup>
import { onMounted } from 'vue'

onMounted(() => {
console.log(`組件現在已經掛載。`)
})
</script>

還有其他鉤子會在實例的不同生命週期階段被調用,其中最常用的是 onMountedonUpdatedonUnmounted

調用 onMounted 時,Vue 會自動將註冊的回調函數與當前活躍的組件實例關聯起來。這要求這些鉤子必須在組件設置期間同步註冊。例如,不要這樣做:

setTimeout(() => {
onMounted(() => {
// 這樣做不會奏效。
})
}, 100)

注意,這並不意味著調用必須放置在 setup()<script setup> 內部。onMounted() 可以在外部函數中調用,只要調用堆棧是同步的,並且源自 setup() 內部即可。

Q:為什麼不會奏效?

在 Vue 中,onMounted 鉤子需要在組件的設置階段同步註冊。這是因為 Vue 需要在組件實例的生命週期內部確保所有的鉤子都已正確註冊。如果你在非同步操作中(例如 setTimeout)調用 onMounted,這樣的註冊可能會在組件的生命週期階段之外進行,因此不會如預期地工作。

  1. setTimeout 是一個非同步操作,它會在指定的時間(這裡是 100 毫秒)後執行其回調函數。
  2. onMounted 鉤子的註冊會被延遲到 setTimeout 的回調中。由於 setTimeout 是非同步的,這可能會在 Vue 的組件實例已經完成設置之後執行,這時組件的生命週期已經不再適合進行這些鉤子的註冊。
  3. 因此,onMounted 的回調函數可能無法正確地與組件實例關聯,從而導致該鉤子不會如預期執行。
要確保 onMounted 鉤子能正常工作,它應該在組件的設置過程中同步註冊,而不是在非同步操作中。這樣 Vue 可以在適當時間點觸發這些鉤子,保證能正確地執行。

Vue 組件實例的生命周期圖 - Lifecycle Diagram​

下圖展示了 Vue 組件實例的生命周期。在你剛開始學習時,可能不需要完全理解其中的每個細節,但隨著你學習和構建更多的項目,它將成為一個有用的參考工具。

raw-image

常見的生命周期鉤子

  • onBeforeMount: 當組件即將被掛載到 DOM 上時調用。此時,虛擬 DOM 已經渲染完畢,但真實的 DOM 還沒有更新。
  • onMounted: 組件已經掛載到 DOM 上時調用。此時,DOM 已經可用,可以進行 DOM 操作。
  • onBeforeUpdate: 當組件的響應式數據發生變化並即將更新 DOM 之前調用。可以在這裡查看更新前的狀態。
  • onUpdated: 組件的 DOM 更新完成後調用。此時可以獲取到最新的 DOM 狀態。
  • onBeforeUnmount: 組件即將從 DOM 上移除時調用。可以在這裡進行一些清理工作。
  • onUnmounted: 組件已經從 DOM 上移除後調用。此時組件的所有響應式數據、監聽器等都已經被銷毀。

其他生命周期鉤子

除了上面提到的常見鉤子外,還有一些其他鉤子在特定場景下非常有用:

  • onActivated: 當組件從 <keep-alive> 緩存中激活時調用。
  • onDeactivated: 當組件被 <keep-alive> 緩存時調用。
  • onErrorCaptured: 當捕獲到組件內部的錯誤時調用,用於錯誤邊界處理。
<template>
<div>
<p>Component Lifecycle Hooks Example</p>
</div>
</template>

<script setup>
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onActivated, onDeactivated, onErrorCaptured } from 'vue'

onBeforeMount(() => {
console.log('beforeMount - 組件即將掛載')
})

onMounted(() => {
console.log('mounted - 組件已掛載')
})

onBeforeUpdate(() => {
console.log('beforeUpdate - 組件即將更新')
})

onUpdated(() => {
console.log('updated - 組件已更新')
})

onBeforeUnmount(() => {
console.log('beforeUnmount - 組件即將銷毀')
})

onUnmounted(() => {
console.log('unmounted - 組件已銷毀')
})

onActivated(() => {
console.log('activated - 組件已激活')
})

onDeactivated(() => {
console.log('deactivated - 組件已停用')
})

onErrorCaptured((err, instance, info) => {
console.error('errorCaptured - 捕獲到錯誤:', err, info)
})
</script>
beforeMount - 組件即將掛載
mounted - 組件已掛載
beforeUpdate - 組件即將更新
updated - 組件已更新
activated - 組件已激活
deactivated - 組件已停用
beforeUnmount - 組件即將銷毀
unmounted - 組件已銷毀
errorCaptured - 捕獲到錯誤: ...

請注意,如果你的組件沒有使用 <keep-alive>,則 activateddeactivated 鉤子不會觸發。如果你的組件或其子組件沒有拋出錯誤,則 errorCaptured 鉤子也不會觸發。

若要了解所有生命周期鉤子及其相應的使用案例,請查閱 Vue 的生命周期鉤子 API 參考文件。這些鉤子允許你在 Vue 組件實例的不同階段執行自定義代碼,使你能夠更靈活地控制組件的行為。

Q:什麼是<keep-alive>?

<keep-alive> 是 Vue 提供的一個內建組件,用於包裹動態組件,從而在其激活和停用之間保留組件的狀態或避免重新渲染。這在需要在不同視圖之間切換時非常有用,例如導航標籤或多頁應用。

生命週期鉤子的作用

  1. activated 鉤子
    • 當組件被 <keep-alive> 包裹且激活時(即重新顯示)會觸發。
    • 可以在這裡執行一些初始化工作或重新設置一些狀態。
  2. deactivated 鉤子
    • 當組件被 <keep-alive> 包裹且停用時(即隱藏)會觸發。
    • 可以在這裡保存狀態或執行一些清理工作。

使用示例

假設有一個包含兩個子組件的 Vue 應用,每個子組件會在不同的選項卡中顯示。我們使用 <keep-alive> 來包裹這些子組件,這樣在切換選項卡時不會重新創建和銷毀組件,而是保留其狀態。

<template>
<div>
<button @click="currentView = 'view1'">View 1</button>
<button @click="currentView = 'view2'">View 2</button>

<keep-alive>
<component :is="currentView"></component>
</keep-alive>
</div>
</template>

<script setup>
import { ref } from 'vue'
import View1 from './View1.vue'
import View2 from './View2.vue'

const currentView = ref('view1')
</script>

有兩個按鈕,分別用來切換當前顯示的視圖。

  1. @click="currentView = 'view1'":點擊這個按鈕會將 currentView 設置為 'view1'
  2. @click="currentView = 'view2'":點擊這個按鈕會將 currentView 設置為 'view2'
  3. <keep-alive> 是一個 Vue 的內建組件,用來包裹動態組件。它會在組件激活和停用之間保持其狀態,不會每次都重新創建和銷毀組件。
  4. <component :is="currentView"></component><component> 是一個動態組件,可以根據 currentView 的值來渲染不同的組件。currentView 的值決定了哪個組件會被渲染。
  5. :is 是一個綁定屬性,用來指定要渲染的組件名稱。這個屬性可以接受一個字符串或一個組件對象。

子組件View1.vue中的 activateddeactivated

<template>
<div>
<p>This is View 1</p>
</div>
</template>

<script setup>
import { onActivated, onDeactivated } from 'vue'

onActivated(() => {
console.log('View 1 is activated')
})

onDeactivated(() => {
console.log('View 1 is deactivated')
})
</script>

類似的子組件 View2.vue

<template>
<div>
<p>This is View 2</p>
</div>
</template>

<script setup>
import { onActivated, onDeactivated } from 'vue'

onActivated(() => {
console.log('View 2 is activated')
})

onDeactivated(() => {
console.log('View 2 is deactivated')
})
</script>

運行結果

當你在選項卡之間切換時,你會在控制台看到類似以下的輸出:

View 1 is activated
View 1 is deactivated
View 2 is activated
View 2 is deactivated
生命週期這玩意常常搞得我一個頭兩個大~
每個鉤子放log,看看每個週期的先後順序跟邏輯
然後就是觀察自動同步的時候是哪個週期?

Q:自動同步在哪個週期?

<template>
<div>
<p>Component Lifecycle Hooks Logging Example</p>
<button @click="updateMessage">Update Message</button>
<p>{{ message }}</p>
</div>
</template>

<script setup>
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'

const message = ref('Hello, Vue!')

// 生命週期鉤子放置 log
onBeforeMount(() => {
console.log('beforeMount - 組件即將掛載')
})

onMounted(() => {
console.log('mounted - 組件已掛載')
})

onBeforeUpdate(() => {
console.log('beforeUpdate - 組件即將更新')
})

onUpdated(() => {
console.log('updated - 組件已更新')
})

onBeforeUnmount(() => {
console.log('beforeUnmount - 組件即將銷毀')
})

onUnmounted(() => {
console.log('unmounted - 組件已銷毀')
})

// 更新消息的方法
const updateMessage = () => {
message.value = 'Message updated!'
}
</script>

在上述示例中,當點擊按鈕更新消息時,可以看到 beforeUpdateupdated 鉤子的觸發順序。這表明在數據變化後,Vue 開始自動同步 DOM,在此期間 beforeUpdate 鉤子被觸發,DOM 更新完成後 updated 鉤子被觸發。

1會員
24內容數
分享生活趣事~
留言0
查看全部
發表第一個留言支持創作者!
卡關的人生 的其他內容
使用 v-bind 可以將 HTML 屬性、樣式或類別綁定到 Vue 的數據,實現單向數據綁定。而 v-model 則是用於表單元素的雙向數據綁定,使輸入和數據同步更新。使用 v-bind 可以讓我們綁定非字符串值,例如布爾值或對象,從而在處理更複雜的應用場景時更為靈活。
Vue.js 的事件修飾符提供了一種簡化和直觀的方式來處理事件。與傳統 JavaScript 中需要手動檢查條件和處理事件相比,Vue 的修飾符(如 .prevent、.stop、.enter)使代碼更加清晰和易於管理。這些修飾符直接在模板中指定事件行為,減少了樣板代碼,提升了可讀性。
v-for 用於渲染陣列或物件列表,支持索引和嵌套。使用 key 來提高渲染效率。v-if 和 v-for 不應同時在同一節點上使用。
Conditional Rendering 根據條件決定是否渲染元素。Vue.js 的 v-if 在條件為真時渲染,v-else-if 處理額外條件,v-show 始終渲染元素但用 CSS 控制顯示。v-if 會創建或銷毀元素,v-show 只改變顯示樣式。
這篇文章介紹了在 Vue.js 前端框架中如何有效地綁定 Class 和 Style。透過使用 v-bind 指令,使用者可以動態地切換元素的類別和內聯樣式,這不僅能夠簡化程式碼,還能防止錯誤的發生。文章中探討了物件和陣列綁定的使用情境,以及如何在組件中應用這些技術,從而提升開發效率與程式的可讀性。
本文介紹了計算屬性(Computed Properties)的基本概念及其在前端框架中的應用,特別是 Vue.js。計算屬性允許我們根據其他響應式數據進行計算並且自動跟蹤依賴,避免不必要的重複計算。本文還探討瞭如何使用可寫入的計算屬性,以及最佳實踐建議,以確保性能與代碼的可讀性。
使用 v-bind 可以將 HTML 屬性、樣式或類別綁定到 Vue 的數據,實現單向數據綁定。而 v-model 則是用於表單元素的雙向數據綁定,使輸入和數據同步更新。使用 v-bind 可以讓我們綁定非字符串值,例如布爾值或對象,從而在處理更複雜的應用場景時更為靈活。
Vue.js 的事件修飾符提供了一種簡化和直觀的方式來處理事件。與傳統 JavaScript 中需要手動檢查條件和處理事件相比,Vue 的修飾符(如 .prevent、.stop、.enter)使代碼更加清晰和易於管理。這些修飾符直接在模板中指定事件行為,減少了樣板代碼,提升了可讀性。
v-for 用於渲染陣列或物件列表,支持索引和嵌套。使用 key 來提高渲染效率。v-if 和 v-for 不應同時在同一節點上使用。
Conditional Rendering 根據條件決定是否渲染元素。Vue.js 的 v-if 在條件為真時渲染,v-else-if 處理額外條件,v-show 始終渲染元素但用 CSS 控制顯示。v-if 會創建或銷毀元素,v-show 只改變顯示樣式。
這篇文章介紹了在 Vue.js 前端框架中如何有效地綁定 Class 和 Style。透過使用 v-bind 指令,使用者可以動態地切換元素的類別和內聯樣式,這不僅能夠簡化程式碼,還能防止錯誤的發生。文章中探討了物件和陣列綁定的使用情境,以及如何在組件中應用這些技術,從而提升開發效率與程式的可讀性。
本文介紹了計算屬性(Computed Properties)的基本概念及其在前端框架中的應用,特別是 Vue.js。計算屬性允許我們根據其他響應式數據進行計算並且自動跟蹤依賴,避免不必要的重複計算。本文還探討瞭如何使用可寫入的計算屬性,以及最佳實踐建議,以確保性能與代碼的可讀性。
你可能也想看
Google News 追蹤
Thumbnail
本專欄將提供給您最新的市場資訊、產業研究、交易心法、精選公司介紹,以上內容並非個股分析,還請各位依據自身狀況作出交易決策。歡迎訂閱支持我,獲得相關內容,也祝您的投資之路順遂! 每年 $990 訂閱方案👉 https://reurl.cc/VNYVxZ 每月 $99 訂閱方案👉https://re
Thumbnail
如何在 Vite 專案中安裝和設置 TypeScript 及路徑別名的步驟,包括安裝必要的依賴、配置 vite.config.js、tsconfig.json 的設置,及如何創建類型聲明文件來正確識別 .vue 文件。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
前言 從零開始構建一個 DateTimePicker 可能看起來令人畏懼,但試想一下你將獲得的靈活性和控制力。在這個系列中,我們將逐步揭開構建過程的神秘面紗,讓您能夠創建一個完全符合需求的自定義 DateTimePicker。 本文章,屬於付費系列的文章,這篇文章,我會希望讀者可以得到的
Thumbnail
本章節提供了關於Typescript中流程控制元素的詳細介紹,包括if, else if, else語句,三元運算子,switch語句,各種for迴圈,while迴圈,循環嵌套和控制迴圈語句(break,continue和標籤)的使用。
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
本專欄將提供給您最新的市場資訊、產業研究、交易心法、精選公司介紹,以上內容並非個股分析,還請各位依據自身狀況作出交易決策。歡迎訂閱支持我,獲得相關內容,也祝您的投資之路順遂! 每年 $990 訂閱方案👉 https://reurl.cc/VNYVxZ 每月 $99 訂閱方案👉https://re
Thumbnail
如何在 Vite 專案中安裝和設置 TypeScript 及路徑別名的步驟,包括安裝必要的依賴、配置 vite.config.js、tsconfig.json 的設置,及如何創建類型聲明文件來正確識別 .vue 文件。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
前言 從零開始構建一個 DateTimePicker 可能看起來令人畏懼,但試想一下你將獲得的靈活性和控制力。在這個系列中,我們將逐步揭開構建過程的神秘面紗,讓您能夠創建一個完全符合需求的自定義 DateTimePicker。 本文章,屬於付費系列的文章,這篇文章,我會希望讀者可以得到的
Thumbnail
本章節提供了關於Typescript中流程控制元素的詳細介紹,包括if, else if, else語句,三元運算子,switch語句,各種for迴圈,while迴圈,循環嵌套和控制迴圈語句(break,continue和標籤)的使用。
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找