Skip to content

Vue 3 生命週期完全指南:Composition API 鉤子的觸發順序與效能優化

Vue 3 生命週期:onMounted 與 onUnmounted

在開發 Vue 3 應用程式時,理解元件從建立、掛載、更新到銷毀的整個生命週期(Lifecycle),是編寫高效能、低耦合程式碼的關鍵基本功。

Vue 3 引入了 Composition API,使得生命週期鉤子(Lifecycle Hooks)的宣告方式與 Vue 2 有了顯著的不同。本文將帶您全面掌握 Vue 3 生命週期的運作機制以及實戰中的效能優化心法。

生命週期流程

這裡展示了完整的 Vue 生命週期流程,每個 Vue 元件從被建立到被銷毀,會歷經一系列的生命週期階段。Vue 在每個關鍵時刻都提供了對應的生命週期函式,讓您可以在特定時機插入自訂邏輯。

在 Composition API 中,所有生命週期鉤子都在 setup 內部呼叫,以 on 開頭命名。

【建立階段】

  setup()           ← 所有 Composition API 邏輯在這裡(無法存取 DOM)

【掛載】

  onBeforeMount()   ← DOM 尚未建立,很少使用

  onMounted()       ← DOM 已建立,最常用

【資料更新】

  onBeforeUpdate()  ← DOM 更新前

  onUpdated()       ← DOM 更新後

【銷毀階段】

  onBeforeUnmount() ← 元件即將銷毀

  onUnmounted()     ← 元件已銷毀,清理資源的地方

其中 掛載階段只會發生一次更新階段則會隨著響應式資料的變動反覆觸發,而 銷毀階段 發生在元件被移除時,例如:路由切換、v-if 條件不再成立、或 v-for 清單中的項目被移除。

生命週期語法使用

生命週期鉤子必須從 vue 匯入,並在 setup同步呼叫。以下範例把所有鉤子都印出來,可以直接貼到元件裡觀察觸發順序:

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

console.log("setup");

onBeforeMount(() => {
  console.log("onBeforeMount");
});

onMounted(() => {
  console.log("onMounted");
});

onBeforeUpdate(() => {
  console.log("onBeforeUpdate");
});

onUpdated(() => {
  console.log("onUpdated");
});

onBeforeUnmount(() => {
  console.log("onBeforeUnmount");
});

onUnmounted(() => {
  console.log("onUnmounted");
});
</script>

鉤子不能寫在非同步流程裡

Vue 是靠 目前正在執行的元件實體 來決定鉤子要註冊給誰,因此鉤子只能在 setup 中同步呼叫。寫在 setTimeoutawait 之後,Vue 已經找不到對應的元件,註冊會直接失效。

同一個鉤子 可以註冊多次,Vue 會依註冊順序依序執行。這個特性讓每個 Composable 都能自己管理自己的掛載與清理,不必把邏輯集中到元件裡。

各階段適合做什麼

階段適合做的事要避免的事
setup建立 refcomputed、註冊 watch、發送不需要 DOM 的 API 請求存取 template 中的 DOM 元素或 ref 綁定的節點
onBeforeMount幾乎不需要用到,偶爾用於掛載前的最後一次資料整理操作 DOM,此時尚未產生
onMounted操作實體 DOM、初始化第三方套件、建立事件監聽與計時器把每次資料變動都要做的事寫在這裡,它只執行一次
onBeforeUpdate記錄更新前的 DOM 狀態,例如:捲軸位置、輸入框游標修改響應式狀態
onUpdated讀取更新後的 DOM 尺寸或位置修改響應式狀態,會造成無窮更新迴圈
onBeforeUnmount需要讀取 DOM 或元件狀態的清理工作建立新的訂閱或請求
onUnmounted解除事件監聽、清除計時器、關閉連線存取已被移除的 DOM

想直接看這些階段的完整程式碼,可以接著閱讀 核心生命週期實戰場景

結論:生命週期效能優化最佳實踐

為了確保 Vue 3 應用程式具有極佳的效能與搜尋引擎友善度,請遵循以下核心原則:

  • 不要在 onUpdated 中修改響應式狀態:在 onUpdated 中修改資料會再次觸發資料變更,進而重新觸發更新,這極易導致 無窮更新迴圈,造成網頁卡死。真的需要依資料變動執行動作時,請改用 watch
  • 善用非同步元件降低初始載入時間:結合生命週期,非核心元件可以使用 defineAsyncComponent() 進行延遲載入,優化 Google Core Web Vitals 的 LCP(最大內容繪製)指標。
  • 精準控管副作用:在生命週期之外,例如:非同步流程中建立的監聽器或訂閱,必須在 onUnmounted 中確實呼叫其銷毀函數,以免造成效能浪費。
  • 只在需要 DOM 時才等到 onMounted:不依賴 DOM 的請求寫在 setup 就能更早發出,縮短使用者看到資料的等待時間。

同場加映:Vue 2 vs Vue 3 生命週期對比

在 Vue 3 的 Composition API 中,程式碼的核心入口是 setup() 函數。因此,Vue 2 中的 beforeCreatecreated 階段,在 Vue 3 中直接由 setup() 函數本身取代,無需任何額外的鉤子。

其他的生命週期鉤子則加上了 on 前綴,並且需要從 vue 中明確匯入:

Vue 2
Options API
Vue 3
Composition API
觸發時機與用途
beforeCreate / createdsetup()元件初始化,建立響應式狀態。此時 DOM 尚未產生。
beforeMountonBeforeMount組件即將被掛載到 DOM 之前執行。
mountedonMounted組件已成功掛載到 DOM。適合執行 API 請求、DOM 操作
beforeUpdateonBeforeUpdate響應式資料改變,但 DOM 尚未重新渲染。
updatedonUpdated資料改變且 DOM 已完成更新。避免在此修改狀態以防無窮迴圈。
beforeDestroyonBeforeUnmount元件即將被銷毀(卸載)前。適合清除定時器、解除全域事件
destroyedonUnmounted元件已完全銷毀,所有專屬監聽器與子組件皆已釋放。

常見問題

Vue 3 為什麼沒有 beforeCreate 與 created?

因為 <script setup> 本身就等於這兩個階段。setup 的程式碼在元件實體建立時同步執行,響應式狀態也在此建立,所以不需要額外的鉤子。

API 請求要寫在 setup 還是 onMounted?

兩者都可以發送請求,差別在於是否需要 DOM。若請求結果只是填進響應式狀態交給模板渲染,寫在 setup 可以更早發出;若需要在拿到資料後操作實體 DOM,例如:初始化圖表,就要寫在 onMounted

為什麼不能在 onUpdated 裡修改響應式狀態?

onUpdated 在 DOM 更新後觸發,此時修改狀態會再次觸發更新,更新完又進入 onUpdated,形成 無窮更新迴圈 導致頁面卡死。需要依資料變動執行動作時,應改用 watch

onBeforeUnmount 與 onUnmounted 該用哪一個清理資源?

需要讀取即將消失的 DOM 或元件狀態時用 onBeforeUnmount,此時元件仍然完整。單純解除計時器、事件監聽或連線這類與 DOM 無關的清理,寫在 onUnmounted 也可以。

生命週期鉤子可以寫在非同步回呼裡嗎?

不行。鉤子必須在 setup 中同步呼叫,Vue 才能把它綁定到目前的元件實體。寫在 setTimeoutawait 之後註冊會失效,開發模式下還會出現警告。

同一個鉤子可以註冊多次嗎?

可以。多次呼叫 onMounted 會依註冊順序全部執行,這也是 Composable 能各自管理自己的生命週期而不互相干擾的原因。

延伸閱讀