iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0
Vue.js

需求至上的 Vue 魔法之旅系列 第 23

Chapter 3:Vue 魔法生命師法順序 — 觀察、召喚與解除的時機

  • 分享至 

  • xImage
  •  

前言

在飲料魔法學院裡,每一個元件(Component)都不是靜止的存在。
它們誕生於魔法師的召喚(onMounted),在運行中感受能量波動(watch / watchEffect),
最後在結束時歸於靜寂(onUnmounted)。

這些過程合稱為「Vue 的生命週期(Lifecycle Hooks)」,
是每一位前端魔法師必須熟記的法術節奏。

今天的學習目標是──
讓我們不只是寫出「會動」的元件,
而是能理解「它何時開始運作、何時該停止魔力」的節奏。


一、魔法生命師法順序:理解元件的誕生與消逝

使用者故事(User Story)

使用者 需求 原因
前端工程師 想在元件出現時載入資料 若放錯時機(如 beforeMount),可能造成畫面閃爍或資料錯亂
前端工程師 想監控資料變化、更新畫面 若監聽不當,可能導致效能下降或重複請求
前端工程師 想在頁面離開時清除監聽器或計時器 若未清除,可能產生記憶體洩漏或異常錯誤

🧙‍ 魔法原則:「每一段魔法都應該有開啟與關閉的時刻
若你只學會召喚,卻忘記解除,那就是不完全的魔法師。


為什麼生命週期很重要?

生命週期就像元件的呼吸與心跳
若你在錯誤的時間點執行請求、操作 DOM 或監聽事件:

  • 資料可能還沒載入完畢,導致渲染失敗
  • 頁面切換後仍執行 setInterval → 記憶體洩漏
  • 💥 watch 寫錯會導致無限循環或效能暴衝

Vue 的生命週期階段圖(魔法師的修行路)

https://ithelp.ithome.com.tw/upload/images/20251007/201210527qkEuVrfnt.png

  1. setup() — 魔力的源頭
    宣告 reactive / ref、注入 store,設定所有初始能量。
    → 此時元件尚未渲染,但狀態樹已生成。

  2. onBeforeMount — 魔力聚集
    DOM 尚未出現在畫面中。可以在這裡做最後預備或初始判斷。

  3. onMounted — 魔力實體化
    元件正式出現在頁面上!這時候才能安全地操作 DOM、呼叫 API、啟動監聽。

  4. onBeforeUpdate / onUpdated — 魔力流動與再結構
    資料改變 → 頁面要重新渲染。
    onBeforeUpdate 先暫停舊能量(如清除動畫),
    onUpdated 再重新開啟(例如重啟動畫或更新視覺效果)。

  5. onBeforeUnmount / onUnmounted — 魔法的歸寂
    元件即將消失,釋放所有監聽器、計時器與全域綁定,
    否則殘留的魔力(setInterval、window 事件)可能導致錯誤或記憶體洩漏。


💡 這張圖的重點是:「State 隨生命週期的變化流動」
你不只是知道函式何時執行,而是理解資料與 DOM 的「生滅節奏」。


流程說明(文字搭配 Flowchart 一起用)


階段 說明 常見用途
setup() 組件建立時執行一次 初始化變數、注入 store
onBeforeMount 元件準備掛載 seldom 使用(預備階段)
onMounted 元件已插入 DOM 發 API、啟動監聽或動畫
onBeforeUpdate 重新渲染前 停止計時、保存狀態
onUpdated DOM 更新完成 DOM 依賴更新後動作
onBeforeUnmount 元件卸載前 清除計時或監聽
onUnmounted 元件銷毀完成 記錄離場事件、釋放資源

二、實作:任務看板的魔法生命軌跡

我們以一個小元件「任務觀測水晶」為例,
它會在誕生時載入任務、在過程中監看變化、最後清除魔法能量。

今天我們就以輕鬆的角度來看vue的生命週期


TaskWatcher.vue

<script setup>
import { ref, onMounted, onUnmounted, watchEffect } from 'vue'

const tasks = ref([])
const loading = ref(true)
let intervalId = null

//  召喚階段:載入初始資料
onMounted(() => {
  console.log(' onMounted: 任務觀測水晶啟動')
  loadTasks()
  // 每 5 秒刷新資料
  intervalId = setInterval(loadTasks, 5000)
})

// 👁 持續觀測能量流動
watchEffect(() => {
  if (tasks.value.length > 5) {
    console.log(' 偵測到任務過多,請儘快處理!')
  }
})

// 🌫 結界解除階段
onUnmounted(() => {
  console.log(' onUnmounted: 清除計時器與魔力痕跡')
  clearInterval(intervalId)
})

function loadTasks() {
  loading.value = true
  setTimeout(() => {
    // 模擬 API 載入
    tasks.value = [
      { id: 1, name: '調配草莓拿鐵' },
      { id: 2, name: '修復冰魔法陣' },
      { id: 3, name: '訓練新學徒' },
    ]
    loading.value = false
  }, 800)
}
</script>

<template>
  <div class="task-crystal">
    <h3>任務觀測水晶</h3>
    <p v-if="loading"> 正在觀測任務流...</p>
    <ul v-else>
      <li v-for="task in tasks" :key="task.id">
        {{ task.name }}
      </li>
    </ul>
  </div>
</template>

<style scoped>
.task-crystal {
  border: 2px solid #a78bfa;
  border-radius: 12px;
  padding: 1em;
  background: #faf5ff;
}
</style>

📜 實作對應的生命週期階段

階段 動作 對應程式
onMounted 初始任務載入、開啟定時刷新 loadTasks()setInterval()
watchEffect 偵測任務變化、即時回報 watchEffect(() => {...})
onUnmounted 清除資源、停止監聽 clearInterval(intervalId)

三、任務運作時序圖(Vue 元件的一生)

https://ithelp.ithome.com.tw/upload/images/20251007/20121052AOS9gArewu.png


四、總結:魔法師的呼吸節奏

  • onMounted → 元件出生,召喚魔力
  • watch / watchEffect → 監控能量流動
  • onUnmounted → 回收魔法、清理戰場

建議修煉方向:

  1. 在專案中為每個重要元件建立「生命週期日誌」,記錄進出時間。
  2. 在資料請求(API)與事件監聽(scroll、resize)中,務必在 onUnmounted 解除
  3. 若元件間需要通訊,利用 emitPinia 讓狀態同步,而不是直接操作 DOM。
  4. 進一步可以嘗試 onBeforeUpdateonUpdated,觀察畫面更新時的節奏。

今日成就解鎖

你學會了「Vue 的呼吸術」,
讓每個元件都能在正確的時間呼吸、觀測與歸靜。


今天算是一個過度,但是重要的章節

因為一個程式或是套件的生命週期特別重要

你才會知道他在哪邊呼叫或是使用~

必秒造成問題~

今天的概念學習完後我們就可以規劃最後一章的內容了(主要是會補實戰的一些技巧vue CICD config或是i18n)


上一篇
Day 16 : 結界與通行證:登入、權限與路由守衛
下一篇
Day 17 : 多語系施法術:Vue i18n 靜態 + 後端動態字典完整實戰
系列文
需求至上的 Vue 魔法之旅24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言