本文 AI 產出,尚未審核

Vue3 錯誤處理與除錯:使用 Vue Devtools 進行有效除錯


簡介

在開發 Vue3 應用程式時,錯誤的即時偵測與快速定位 是提升開發效率與產品品質的關鍵。即使寫得再小心,複雜的 UI、非同步請求或是第三方套件都可能在執行階段拋出意外錯誤,若無有效的除錯工具,開發者往往只能靠 console.log 逐行追蹤,既費時又容易遺漏細節。

Vue Devtools(以下簡稱 Devtools)是官方提供的瀏覽器擴充套件,除了可以檢視元件樹、狀態與路由外,還內建 錯誤捕捉、事件追蹤、性能分析 等功能。善用 Devtools,開發者可以在 瀏覽器即時看到錯誤資訊、回溯元件的變化,大幅縮短除錯時間。

本篇文章將從 核心概念實作範例常見陷阱與最佳實踐,以及 實際應用場景 四個面向,完整說明在 Vue3 專案中如何使用 Devtools 進行除錯,幫助初學者到中階開發者快速上手並養成良好的除錯習慣。


核心概念

1. Vue Devtools 的基本組成

功能區塊 說明
Components 顯示目前渲染的元件樹,點擊可檢視 props、state、computed、emit 事件等。
Pinia / Vuex 若使用 Pinia 或 Vuex,會自動顯示 store 的狀態與變化紀錄。
Router 監控 Vue Router 的路由變化,顯示當前路由資訊與參數。
Performance 記錄渲染與更新的時間線,協助找出效能瓶頸。
Events 捕捉元件間的自訂事件($emit)與原生 DOM 事件。
Console 整合 Vue 的錯誤訊息與警告,提供點擊跳轉到原始碼的功能。

重點:Devtools 會在 開發環境 自動啟用 devtools 設定,正式環境 (production) 若未特別設定則不會暴露錯誤資訊,以免洩漏敏感資訊。

2. 啟用與設定 Devtools

  1. 安裝擴充套件

    • Chrome / Edge: 前往 Chrome Web Store 搜尋「Vue.js devtools」並安裝。
    • Firefox: 前往 Add‑ons Marketplace 安裝。
  2. 在 Vue3 專案中啟用(若使用 Vite)

    npm install -D @vue/devtools
    
    // vite.config.ts
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    
    export default defineConfig({
      plugins: [vue()],
      // 只在開發環境開啟 devtools
      define: {
        __VUE_PROD_DEVTOOLS__: false,
      },
    })
    
  3. 在 main.js 中顯式開啟(可選)

    import { createApp } from 'vue'
    import App from './App.vue'
    
    const app = createApp(App)
    
    // 在非生產環境啟用 Vue Devtools
    if (process.env.NODE_ENV !== 'production') {
      app.config.devtools = true
    }
    
    app.mount('#app')
    

3. 捕捉元件錯誤的機制

Vue3 為每個元件提供了 errorCaptured 鉤子,讓開發者自行處理子元件的錯誤。Devtools 會自動偵測這些錯誤並在 Console 分頁中顯示。

export default {
  name: 'ParentComponent',
  // 捕捉子元件錯誤
  errorCaptured(err, instance, info) {
    console.error('捕捉到子元件錯誤:', err)
    // 回傳 false 可阻止錯誤向上冒泡
    return false
  },
}

技巧:在 errorCaptured 中加入 console.error,配合 Devtools 的 Stack Trace 功能,能直接點擊跳到拋出錯誤的行號。

4. 使用「事件追蹤」定位問題

當 UI 行為不符合預期時,事件流 常是疑點所在。Devtools 的 Events 分頁會列出所有 $emit、DOM 事件及其 payload,讓你一眼看出 哪個元件在什麼時候發出錯誤訊號

<!-- Child.vue -->
<template>
  <button @click="handleClick">點我</button>
</template>

<script setup>
import { defineEmits } from 'vue'
const emit = defineEmits(['error'])

function handleClick() {
  // 故意拋出錯誤事件
  emit('error', new Error('模擬錯誤'))
}
</script>

在 Devtools 的 Events 分頁,你會看到 error 事件被觸發,點擊即可檢視 payload(即 Error 物件),快速定位問題根源。

5. 觀察 Vue3 的響應式系統

Devtools 能即時顯示 reactiverefcomputed 的當前值,且在值變化時會自動更新。這對於除錯 資料不一致更新未觸發 的情況非常有幫助。

import { ref, computed } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const double = computed(() => count.value * 2)

    function inc() {
      count.value++
    }

    return { count, double, inc }
  },
}

在 Devtools 的 ComponentssetupState 中,你可以即時看到 countdouble 的值,點擊 Track 按鈕還能把它們加入 Timeline,觀察變化曲線。


程式碼範例

以下提供 5 個實用範例,示範如何在 Vue3 中結合 Devtools 進行除錯。每個範例皆附上註解說明,方便你直接在專案中套用。

範例 1:捕捉非同步請求錯誤

// src/components/AsyncFetcher.vue
<template>
  <div>
    <p v-if="error" class="error">{{ error.message }}</p>
    <p v-else-if="loading">載入中...</p>
    <pre v-else>{{ data }}</pre>
  </div>
</template>

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

const data = ref(null)
const loading = ref(true)
const error = ref(null)

async function fetchData() {
  try {
    const res = await fetch('https://api.example.com/items')
    if (!res.ok) throw new Error(`HTTP ${res.status}`)
    data.value = await res.json()
  } catch (e) {
    // 把錯誤記錄到 console,Devtools 會顯示完整 stack trace
    console.error('取得資料失敗:', e)
    error.value = e
  } finally {
    loading.value = false
  }
}

onMounted(fetchData)
</script>

<style scoped>
.error { color: red; }
</style>

說明:當 API 回傳錯誤時,console.error 讓 Devtools 的 Console 分頁直接顯示錯誤訊息與堆疊,點擊即可跳回 fetchData 函式的拋錯位置。

範例 2:使用 errorCaptured 捕捉子元件錯誤

// src/components/Parent.vue
<template>
  <ChildComponent />
</template>

<script>
import ChildComponent from './Child.vue'

export default {
  components: { ChildComponent },
  errorCaptured(err, instance, info) {
    // 在父層集中處理子層錯誤
    console.warn('Parent 捕捉到錯誤:', err.message, '| info:', info)
    // 回傳 false 防止錯誤向上冒泡至全局
    return false
  },
}
</script>
// src/components/Child.vue
<template>
  <button @click="boom">觸發錯誤</button>
</template>

<script setup>
function boom() {
  // 故意拋出錯誤
  throw new Error('Child component 發生未捕獲的錯誤')
}
</script>

提示:在 Devtools 的 ComponentsChildComponenterror 分頁,你會看到錯誤被捕捉的資訊,配合 Stack Trace 可快速定位 boom 函式。

範例 3:追蹤自訂事件的 payload

<!-- src/components/Notifier.vue -->
<template>
  <button @click="notify">發送通知</button>
</template>

<script setup>
import { defineEmits } from 'vue'
const emit = defineEmits(['notify'])

function notify() {
  const payload = {
    id: Date.now(),
    message: '這是一條測試通知',
    level: 'info',
  }
  emit('notify', payload)
}
</script>
// src/App.vue
<template>
  <Notifier @notify="handleNotify" />
</template>

<script setup>
import Notifier from './components/Notifier.vue'

function handleNotify(payload) {
  console.log('收到通知:', payload)
}
</script>

使用方式:開啟 Devtools 的 Events 分頁,點擊 notify 事件即可看到 payload 的完整內容,協助驗證資料結構是否正確。

範例 4:觀察 Pinia Store 的變化

// src/stores/counter.js
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)

  function inc() {
    count.value++
  }

  function dec() {
    count.value--
  }

  return { count, inc, dec }
})
<!-- src/components/Counter.vue -->
<template>
  <div>
    <p>計數器:{{ counter.count }}</p>
    <button @click="counter.inc">+1</button>
    <button @click="counter.dec">-1</button>
  </div>
</template>

<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>

Devtools 操作:在 Pinia 分頁,你可以看到 count 的每一次變化,並可點擊 Time Travel 回到任意一步,驗證狀態變化邏輯是否符合預期。

範例 5:使用 Performance 面板找出渲染瓶頸

<!-- src/components/HeavyList.vue -->
<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.text }}</li>
  </ul>
</template>

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

const items = ref([])

onMounted(() => {
  // 模擬大量資料渲染(10,000 筆)
  const list = []
  for (let i = 0; i < 10000; i++) {
    list.push({ id: i, text: `項目 ${i}` })
  }
  items.value = list
})
</script>

除錯步驟

  1. 開啟 Devtools → Performance
  2. 點擊 Record,觸發 HeavyList 的掛載。
  3. 結束錄製後,時間線會顯示大量的 Component Render,點擊任一節點可看到具體的渲染耗時。
  4. 根據結果,你可以採取 virtual‑list, lazy‑loadmemoization 等優化方式。

常見陷阱與最佳實踐

陷阱 為何會發生 解決方案 / 最佳實踐
Devtools 在 production 被關閉 產線環境預設 app.config.devtools = false,若忘記在開發環境顯式開啟,除錯資訊會消失。 永遠在 main.js 中根據 process.env.NODE_ENV 設定 devtools,或在 Vite 設定 define: { __VUE_PROD_DEVTOOLS__: false }
過度使用 console.log 大量 log 會污染 console,且在 Performance 面板中難以分辨真正的錯誤訊息。 使用 console.errorconsole.warn 分類訊息,並在需要時加入 debugger 中斷點;在 Devtools 的 Console 分頁使用 Filter 功能。
忽略 errorCaptured 的回傳值 若忘記回傳 false,錯誤會向上冒泡至全局,導致應用崩潰。 明確回傳 false 以阻止錯誤冒泡,或在全局 app.config.errorHandler 中統一處理。
未追蹤 Pinia/ Vuex 狀態變化 只看 UI,卻不檢查 store 的變化,容易誤以為是元件問題。 在 Devtools 的 Pinia/Vuex 分頁開啟「Time Travel」,檢查每一次 mutation/action。
忽視性能面板 只關注功能是否正確,忽略渲染時間,長期會導致 UI 卡頓。 每次加入大量資料或新元件時,使用 Performance 面板錄製,確保渲染時間在可接受範圍內。

最佳實踐總結

  1. 保持 Devtools 開啟:開發時一定要確保瀏覽器已安裝且啟用 Vue Devtools。
  2. 分層捕捉錯誤:使用 errorCaptured 捕捉子元件錯誤,並在根元件或全局 errorHandler 中統一記錄。
  3. 善用事件追蹤:對於自訂事件或跨元件通訊,先在 Devtools 的 Events 分頁檢查 payload 正確性。
  4. 觀察響應式變化:在 Components → setupState 中追蹤 refreactivecomputed,必要時加入 Track
  5. 定期檢測性能:在功能完成後,使用 Performance 面板錄製一次,確認渲染與更新時間符合需求。

實際應用場景

場景 1:線上表單驗證失敗,使用者看不到錯誤訊息

  • 問題:表單提交後,後端回傳驗證錯誤,但 UI 沒有顯示。
  • 解決步驟
    1. 在 Devtools 的 Network 分頁確認 API 回傳的錯誤 JSON。
    2. Components → 該表單元件的 data 中檢查 errorMessage 是否被正確設定。
    3. 使用 Console 中的 console.error 訊息,確認錯誤是否在 catch 區塊被吞掉。
    4. 若是 errorCaptured 攔截後未正確傳遞,調整回傳 false 或在 errorHandler 中統一顯示 toast。

場景 2:大型清單渲染卡頓,使用者操作延遲

  • 問題:渲染 5,000 筆資料時,畫面卡住 2~3 秒。
  • 解決步驟
    1. 開啟 PerformanceRecord,觸發清單渲染。
    2. 在時間線中定位到 Component Render,點擊查看是哪個元件佔用最多時間。
    3. 若是 v-for 直接渲染全部項目,改用 virtual‑list(如 vue-virtual-scroller)或 分頁
    4. Components → 該清單元件的 props 中觀察 items 的長度變化,確保不會不必要地重新賦值。

場景 3:子元件拋出未捕獲的錯誤,導致整個頁面白屏

  • 問題:某個子元件在 mounted 時執行第三方庫的初始化失敗,導致全局錯誤。
  • 解決步驟
    1. Console 中看到錯誤堆疊,點擊跳回子元件的 mounted 程式碼。
    2. 在父層加入 errorCaptured,將錯誤轉為 UI 可見的提示。
    3. 若錯誤是非同步的,使用 try…catch 包住 await 呼叫,並在 catchemit('error', e),讓父層透過事件捕捉。
    4. 最後在 Events 分頁確認 error 事件已正確傳遞。

總結

Vue3 搭配官方提供的 Vue Devtools,不僅能讓開發者即時觀察元件結構、狀態與事件,還能透過 Console、Events、Performance 等多元面板,快速定位錯誤根源、追蹤資料變化與優化效能。

本文從 核心概念(Devtools 組件、錯誤捕捉、事件追蹤、響應式觀察)出發,提供 5 個實務範例,再列出 常見陷阱與最佳實踐,最後以 真實開發情境 示範除錯流程。只要遵循以下幾點:

  1. 保持 Devtools 開啟,並在開發環境明確設定 app.config.devtools = true
  2. 分層捕捉錯誤,善用 errorCaptured 與全局 errorHandler
  3. 利用 Events 面板 觀察自訂事件與 payload。
  4. 觀察響應式狀態,即時追蹤 refreactivecomputed 的變化。
  5. 定期使用 Performance 面板,避免 UI 卡頓與不必要的渲染。

就能在 Vue3 專案中建立 高效、可靠的除錯流程,讓開發速度加倍、產品品質更上一層樓。祝你玩得開心,除錯順利!