20
Re:Nuxt 100 天練習曲
Day 20

當網站出錯時 (致命錯誤處理)

Day 20·錯誤處理·error.vue

再完美的程式碼也可能出錯。網路可能中斷、API 可能掛掉。當這些讓網站無法正常運作的「致命錯誤」發生時,我們需要給使用者一個友善的提示,而不是一個冰冷的白畫面或錯誤碼。

1. 網站的「維修中」告示牌:error.vue

當 Nuxt 遇到一個無法處理的致命錯誤時,它會放棄渲染當前的頁面,轉而尋找一個名為 error.vue 的特殊檔案,並顯示它的內容。

您可以把它想像成是商店發生緊急狀況時,掛在外面的「今日盤點,暫停營業」的告示牌。

如何建立這個告示牌?

1

在您專案的根目錄(與 app.vue 同層)建立一個 error.vue 檔案。

2

這個元件會自動接收一個名為 error 的 prop,裡面包含了錯誤的詳細資訊,例如 statusCode (404, 500) 和 statusMessage

error.vue
<script setup>
// Nuxt 會自動把 error 物件傳進來
defineProps({
  error: Object
});

// 點擊按鈕時,清除錯誤並導回首頁
const handleError = () => clearError({ redirect: '/' });
</script>

<template>
  <div class="error-page">
    <h1>Oops!</h1>
    <h2>{{ error.statusCode }} - {{ error.statusMessage }}</h2>
    <p>抱歉,頁面似乎走失了。</p>
    <button @click="handleError">回到首頁</button>
  </div>
</template>

2. 如何手動掛上告示牌:throw createError()

有時候,錯誤不是 Nuxt 自動發現的,而是我們在程式邏輯中判斷出來的。例如,使用者想看一篇文章,但資料庫裡根本沒有這篇文章。

這時,我們需要主動告訴 Nuxt:「嘿,這裡出大問題了,快顯示錯誤頁面!」

最推薦的方法就是使用 throw createError()

最常見的情境:useFetch 後發現找不到資料

pages/posts/[id].vue
<script setup>
const route = useRoute();
const { data: post } = await useFetch(`/api/posts/${route.params.id}`);

// 如果 API 回傳的 post 是 null 或 undefined,就代表找不到這篇文章
if (!post.value) {
  throw createError({ 
    statusCode: 404, 
    statusMessage: '文章不存在 (Article Not Found)',
    fatal: true // fatal: true 會確保觸發全螢幕的 error.vue
  });
}
</script>

當這段程式碼被執行時,Nuxt 就會立刻停止當前頁面的渲染,轉而去顯示我們設計好的 error.vue。

3. 如何撕掉告示牌:clearError()

clearError() 是一個內建的工具函式,它的作用就是清除當前的錯誤狀態,並可選擇性地將使用者導向一個安全的頁面(通常是首頁)。這就是我們在 error.vue 的按鈕上綁定的函式。

clearError 使用範例
// 清除錯誤並重新導向
const handleError = () => {
  clearError({
    redirect: '/' // 導向首頁
  });
}

// 或者只是清除錯誤,留在當前頁面
const handleRetry = () => {
  clearError();
}

今日總結

今天我們學會了如何處理最嚴重的錯誤情況:

建立一個客製化的 error.vue 頁面,提供友善的錯誤提示。

學會如何使用 throw createError() 在適當時機主動觸發錯誤頁面。

使用 clearError() 讓使用者能從錯誤中恢復,並回到網站。

預告:但不是所有錯誤都這麼嚴重。如果只是頁面中的某個小元件出錯,我們不希望它影響到整個頁面,該怎麼辦呢?明天,我們將學習如何處理這種「局部錯誤」。