错误处理 Error handling

了解如何捕获不同生命周期中的错误。

处理错误

Nuxt 3 是一个全栈框架,这意味着在不同的上下文中可能会发生无法预防的用户运行时错误的多种来源:

  1. Vue渲染生命周期错误(SSR+SPA)
  2. API 或 Nitro 服务器生命周期中的错误
  3. 服务器和客户端启动错误(SSR + SPA)
  4. 下载JS chunks出错

Vue渲染生命周期中的错误(SSR+SPA)

您可以使用 onErrorCaptured 挂钩 Vue 错误。

此外,Nuxt 提供了一个 vue:error 挂钩,如果任何错误传播到顶层,该挂钩将被调用。

如果您使用的是错误报告框架,则可以通过 vueApp.config.errorHandler 提供全局处理程序。 它会接收所有 Vue 错误,即使它们已被处理。

使用全局错误报告的示例

js
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.config.errorHandler = (error, context) => {
    // ...
  }
})

服务端和客户端启动错误(SSR+SPA)

如果在启动 Nuxt 应用程序时出现任何错误,Nuxt 将调用 app:error 挂钩。

这包括:

  • 运行 Nuxt 插件
  • 处理 app:createdapp:beforeMount 钩子
  • 将你的 Vue 应用渲染为 HTML(在服务器上)
  • 安装应用程序(在客户端),尽管您应该使用 onErrorCapturedvue:error 处理这种情况
  • 处理 app:mounted 钩子

API 或 Nitro 服务器生命周期中的错误

您目前无法为这些错误定义服务器端处理程序,但可以呈现错误页面(请参阅下一节)。

下载 JS 块时出错

由于网络连接失败或新部署(这会使旧的散列 JS 块 URL 无效),您可能会遇到块加载错误。 Nuxt 通过在路由导航期间无法加载块时执行硬重新加载来提供对处理块加载错误的内置支持。

您可以通过将 experimental.emitRouteChunkError 设置为 false(以完全禁用对这些错误的挂钩)或设置为 manual(如果您想自己处理它们)来更改此行为。 如果你想手动处理块加载错误,你可以查看自动实现的想法。

渲染错误页面

当 Nuxt 遇到致命错误时,无论是在服务器生命周期期间,还是在呈现 Vue 应用程序(SSR 和 SPA)时,它都会呈现 JSON 响应(如果使用 Accept: application/json 标头请求)或 HTML 错误 页。

您可以通过在应用程序的源目录中添加 ~/error.vue 以及 app.vue 来自定义此错误页面。 这个页面只有一个 prop - error,它包含一个错误供你处理。

当您准备好删除错误页面时,您可以调用 clearError 辅助函数,该函数采用可选路径重定向到(例如,如果您想导航到“安全”页面)。

确保在使用依赖于 Nuxt 插件的任何东西之前进行检查,例如 $routeuseRouter,如果插件抛出了错误,那么在您清除错误之前它不会重新运行。

示例

error.vue
vue
<script setup>
const props = defineProps({
  error: Object
})

const handleError = () => clearError({ redirect: '/' })
</script>

<template>
  <button @click="handleError">
    清除错误
  </button>
</template>

错误辅助方法

useError

  • function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>

此函数将返回正在处理的全局 Nuxt 错误。

createError

  • function createError (err: { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error

您可以使用此函数创建带有附加元数据的错误对象。 它可用于您应用程序的 Vue 和 Nitro 部分,并且应该被抛出。

如果你抛出一个用 createError 创建的错误:

  • 在服务器端,它会触发一个全屏错误页面,您可以使用 clearError 清除该页面。
  • 在客户端,它会抛出一个非致命错误供您处理。 如果你需要触发全屏错误页面,那么你可以通过设置 fatal: true 来实现。

示例

pages/movies/[slug
vue
<script setup>
const route = useRoute()
const { data } = await useFetch(`/api/movies/${route.params.slug}`)
if (!data.value)
  throw createError({ statusCode: 404, statusMessage: 'Page Not Found' })
</script>

showError

  • function showError (err: string | Error | { statusCode, statusMessage }): Error

您可以在客户端的任何位置调用此函数,或(在服务器端)直接在中间件、插件或 setup() 函数中调用。 它将触发一个全屏错误页面,您可以使用 clearError 清除该页面。

建议改为使用 throw createError()

clearError

  • function clearError (options?: { redirect?: string }): Promise<void>

该函数将清除当前处理的 Nuxt 错误。 它还需要一个可选的重定向路径(例如,如果您想导航到“安全”页面)。

在您的应用程序中呈现错误

Nuxt 还提供了一个<NuxtErrorBoundary>组件,允许您在应用程序中处理客户端错误,而无需用错误页面替换整个站点。

该组件负责处理在其默认插槽中发生的错误。 在客户端,它会阻止错误冒泡到顶层,并会渲染 #error 插槽。

#error 插槽将接收 error 作为道具。 (如果您设置 error = null,它将触发重新渲染默认插槽;您需要确保首先完全解决错误,否则将再次渲染错误插槽。)

如果您导航到另一条路线,错误将自动清除。

示例

pages/index.vue
vue
<template>
  <!-- 一些内容 -->
  <NuxtErrorBoundary @error="someErrorLogger">
    <!-- 您使用默认插槽来呈现您的内容 -->
    <template #error="{ error }">
      您可以在此处本地显示错误。
      <button @click="error = null">
        这将清除错误。
      </button>
    </template>
  </NuxtErrorBoundary>
</template>