一、生命周期概述
Vue 組件從創建到銷毀的整個過程稱為生命周期,在這個過程中,Vue 會自動觸發一系列的函數,這些函數被稱為生命周期鉤子。通過生命周期鉤子,我們可以在組件的不同階段執行特定的操作,例如初始化數據、發送請求、操作 DOM 等。
Vue 3 的生命周期鉤子與 Vue 2 相比,在命名和使用方式上有一些變化,同時支持選項式 API 和組合式 API 兩種風格。
二、選項式 API 中的生命周期鉤子
選項式 API 中的生命周期鉤子以選項的形式定義在組件中,無需導入即可直接使用。
2.1 常用生命周期鉤子及執行時機
- beforeCreate:在實例初始化之后、數據觀測 (data observer) 和 event/watcher 事件配置之前被調用。此時組件實例的屬性和方法尚未初始化,無法訪問 data、methods 等。
- created:在實例創建完成后被立即調用。此時組件實例已完成數據觀測、屬性和方法的運算,但尚未開始 DOM 編譯,即未掛載到 DOM 上,無法訪問 $el。通常在此鉤子中進行數據初始化、發送初始化請求等操作。
- beforeMount:在掛載開始之前被調用。此時模板已編譯完成,但尚未將編譯好的模板掛載到頁面中,$el 屬性已存在但未掛載。
- mounted:在實例掛載完成后被調用。此時組件已掛載到 DOM 上,可以訪問和操作 DOM 元素,通常在此鉤子中執行需要 DOM 支持的操作,如初始化第三方插件。
- beforeUpdate:在數據更新之前被調用,發生在虛擬 DOM 重新渲染和打補丁之前。可以在此時訪問到更新前的 DOM 狀態。
- updated:在數據更新之后被調用,此時虛擬 DOM 已重新渲染并應用了補丁,組件 DOM 已更新。應避免在此鉤子中修改數據,以免陷入無限循環。
- beforeUnmount:在組件實例卸載之前調用。此時組件實例仍然完全可用,可以在這里執行一些清理操作,如清除定時器、取消事件監聽等。
- unmounted:在組件實例卸載之后調用。此時組件的所有指令和事件監聽器都已被移除,DOM 元素也已從頁面中移除。
2.2 選項式 API 生命周期鉤子使用案例
<template><div><p>{{ message }}</p><button @click="updateMessage">更新消息</button></div></template><script>export default {data() {return {message: '初始消息',timer: null}},beforeCreate() {console.log('beforeCreate 鉤子執行')console.log('此時 data 中的 message:', this.message) // undefined},created() {console.log('created 鉤子執行')console.log('此時 data 中的 message:', this.message) // 初始消息// 發送初始化請求示例console.log('發送初始化數據請求...')},beforeMount() {console.log('beforeMount 鉤子執行')console.log('此時的 $el:', this.$el) // 已存在但未掛載},mounted() {console.log('mounted 鉤子執行')console.log('此時的 $el:', this.$el) // 已掛載到 DOM// 啟動定時器示例this.timer = setInterval(() => {console.log('定時器執行中...')}, 1000)},beforeUpdate() {console.log('beforeUpdate 鉤子執行')console.log('更新前的 message:', this.message)},updated() {console.log('updated 鉤子執行')console.log('更新后的 message:', this.message)},beforeUnmount() {console.log('beforeUnmount 鉤子執行')// 清除定時器clearInterval(this.timer)console.log('定時器已清除')},unmounted() {console.log('unmounted 鉤子執行')console.log('組件已卸載')},methods: {updateMessage() {this.message = '更新后的消息'}}}</script>
在上述案例中,通過在組件選項中定義各個生命周期鉤子,我們可以清晰地看到每個鉤子的執行時機和可執行的操作。
三、組合式 API 中的生命周期鉤子
組合式 API 中的生命周期鉤子需要從 vue 中導入后才能使用,且命名以 on 開頭,例如 onMounted、onUpdated 等。
3.1 常用生命周期鉤子及對應關系
組合式 API 中的生命周期鉤子與選項式 API 中的鉤子一一對應,具體對應關系如下:
- onBeforeMount:對應選項式 API 的 beforeMount
- onMounted:對應選項式 API 的 mounted
- onBeforeUpdate:對應選項式 API 的 beforeUpdate
- onUpdated:對應選項式 API 的 updated
- onBeforeUnmount:對應選項式 API 的 beforeUnmount
- onUnmounted:對應選項式 API 的 unmounted
此外,組合式 API 中沒有直接對應 beforeCreate 和 created 的鉤子,因為在 setup 函數中,代碼的執行時機介于 beforeCreate 和 created 之間,因此可以將原本在 beforeCreate 和 created 中執行的操作直接寫在 setup 函數中。
3.2 組合式 API 生命周期鉤子使用案例
<template><div><p>{{ count }}</p><button @click="count++">增加計數</button></div></template><script setup>import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'const count = ref(0)let timer = null// 相當于 beforeCreate 和 created 鉤子console.log('setup 中執行(相當于 beforeCreate 和 created)')console.log('count 的初始值:', count.value)onBeforeMount(() => {console.log('onBeforeMount 鉤子執行')})onMounted(() => {console.log('onMounted 鉤子執行')// 啟動定時器timer = setInterval(() => {count.value++}, 2000)})onBeforeUpdate(() => {console.log('onBeforeUpdate 鉤子執行,更新前的 count:', count.value)})onUpdated(() => {console.log('onUpdated 鉤子執行,更新后的 count:', count.value)})onBeforeUnmount(() => {console.log('onBeforeUnmount 鉤子執行')// 清除定時器clearInterval(timer)console.log('定時器已清除')})onUnmounted(() => {console.log('onUnmounted 鉤子執行')})</script>
在組合式 API 中,生命周期鉤子以函數的形式使用,需要先導入再調用,每個鉤子函數接收一個回調函數,回調函數中包含該鉤子需要執行的操作。
四、生命周期鉤子的實際應用場景
- 數據初始化:在 created(選項式)或 setup(組合式)中初始化組件所需的數據,例如從本地存儲中讀取數據。
- 發送請求:在 created 或 mounted 中發送異步請求獲取后端數據,mounted 中可以結合 DOM 操作處理請求結果。
- 初始化插件:在 mounted 中初始化需要 DOM 支持的第三方插件,如圖表插件、富文本編輯器等。
- 監聽事件:在 mounted 中為 DOM 元素添加事件監聽器,在 beforeUnmount 中移除監聽器,避免內存泄漏。
- 清理操作:在 beforeUnmount 中清除定時器、取消未完成的請求、解綁自定義事件等,確保組件卸載后不會留下副作用。
五、選項式 API 與組合式 API 生命周期對比
選項式 API 鉤子 | 組合式 API 鉤子 | 執行時機 |
beforeCreate | - | 組件實例初始化前 |
created | - | 組件實例創建后 |
beforeMount | onBeforeMount | 組件掛載前 |
mounted | onMounted | 組件掛載后 |
beforeUpdate | onBeforeUpdate | 數據更新前 |
updated | onUpdated | 數據更新后 |
beforeUnmount | onBeforeUnmount | 組件卸載前 |
unmounted | onUnmounted | 組件卸載后 |
通過對比可以看出,組合式 API 中的生命周期鉤子與選項式 API 中的鉤子功能一致,只是命名和使用方式不同。在實際開發中,可根據項目風格和個人習慣選擇合適的 API 風格。
結語:
接下來我會講解 Vue 3 中組件通信的更多方式,除了之前提到的父傳子,還會介紹子傳父、兄弟組件通信以及跨級組件通信等,并結合案例說明每種方式的實現方法和適用場景。?