错误处理与自定义错误页
本教程共 50 篇 · 第 41 篇 · 更新于 2026-08-08 · 约 8 分钟阅读
本节目标:理解 Nuxt 的错误处理体系,能抛出错误、自定义全站错误页,并在局部优雅地捕获组件错误。
41-1
Nuxt 是全栈框架,错误可能出现在好几个地方:Vue 渲染时的报错、应用启动失败、Nitro 服务端报错、甚至浏览器下载 JS 分块(chunk)失败。SSR 和 CSR 都可能出错,所以不能只在前端兜底。
好消息是:Nuxt 把这些情况归并到一套清晰的 API 里,你只要记住几个核心函数就能应对大多数场景。
41-2
createError 用来创建一个带元数据的错误对象,通常配合 throw 使用。它既能在服务端用,也能在客户端用。
<script setup lang="ts">
const route = useRoute()
const { data } = await useFetch(`/api/movies/${route.params.slug}`)
if (!data.value) {
throw createError({
statusCode: 404,
statusMessage: '页面未找到',
})
}
</script>
createError 接收一个对象,常用字段有:statusCode(HTTP 状态码)、statusMessage(状态文案)、message(错误说明)、fatal(是否致命)。
Note服务端抛出的
createError会触发全屏错误页;客户端抛出的默认是「非致命错误」,由你自行处理。想要客户端也触发全屏错误页,把fatal: true加上即可。
41-3
Nuxt 默认有个错误页,但大多时候你要换成自己的风格。只要在源码根目录(Nuxt 4 是 app/error.vue,与 app.vue 并列)建一个 error.vue:
<script setup lang="ts">
import type { NuxtError } from '#app'
const props = defineProps({
error: Object as () => NuxtError,
})
const handleError = () => clearError({ redirect: '/' })
</script>
<template>
<div>
<h2>{{ error?.statusCode }}</h2>
<p>{{ error?.message }}</p>
<button @click="handleError">回到首页</button>
</div>
</template>
错误页会收到一个 error prop,里面有 statusCode、statusMessage、message 等信息。点击按钮调用 clearError 即可「消除错误状态」,可选重定向到安全页面。
Warning渲染错误页是一次「完整的独立页面加载」,意味着所有中间件会再跑一遍。在中间件里可以用
useError()判断当前是否处于错误态,避免死循环重定向。
41-4
有时候你不想整页崩掉,只想「这块出错就显示个提示」。用 <NuxtErrorBoundary> 包裹内容,错误会被圈在局部:
<template>
<NuxtErrorBoundary @error="someErrorLogger">
<SomeRiskyComponent />
<template #error="{ error, clearError }">
<p>出错了:{{ error }}</p>
<button @click="clearError">重试</button>
</template>
</NuxtErrorBoundary>
</template>
#error 插槽能拿到 error 和 clearError,客户端渲染期间它会阻止错误冒泡到顶层,只替换这一块。
也可以用组合式函数 onErrorCaptured 在 setup 里捕获:
onErrorCaptured((err) => {
console.error('捕获到子组件错误', err)
// 返回 false 阻止错误继续向上传播
return false
})
41-5
想在错误发生时统一上报(比如发到 Sentry),在插件里挂监听最合适:
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
// 上报到监控服务
console.error('全局错误', error, info)
}
nuxtApp.hook('vue:error', (error) => {
console.error('vue:error', error)
})
})
vue:error 基于 onErrorCaptured,能捕获所有冒泡到顶层的 Vue 错误,连已被 onErrorCaptured 处理过的也能收到。
41-6
useError():返回当前正在处理的全局错误,是个 ref。showError(err):在客户端任意时刻调用,触发全屏错误页。官方建议优先用throw createError()。clearError({ redirect }):清除当前错误,可选重定向。
Tip清除错误前,别急着依赖某些插件注入的东西(如
$route、useRouter)。如果那个插件抛过错,在你clearError之前它不会重跑。先确认所需能力可用,再操作。
41-7
Nuxt 3 与 Nuxt 4 的错误处理 API 一致,createError/error.vue/clearError/onErrorCaptured 用法相同。唯一的目录差异是错误页位置:Nuxt 3 在根 error.vue,Nuxt 4 在 app/error.vue。
41-8
Nuxt 的错误体系可以分成三层,别混着用:
- 全屏错误页(
error.vue+createError):整页崩了用。比如路由参数对应的数据不存在,直接throw createError({ statusCode: 404 }),用户看到的是你的错误页,不是白屏。 - 局部边界(
<NuxtErrorBoundary>/onErrorCaptured):只有某一块出错。比如一个第三方图表组件可能崩,把它包起来,崩了只显示「加载失败」提示,页面其他部分照常工作。 - 全局上报(
vue:error/errorHandler,放插件):不阻断用户体验,只负责把错误发到监控后台。
Tip选哪一层的判断标准:这个错误「该不该让用户离开当前页面」。该离开 → 全屏页;不该离开、只是局部坏 → 边界;都不影响、只是想记录 → 上报。
41-9
error.vue 渲染时不会走你平时的 layouts,它是一张独立的全屏页。所以别指望在错误页里用 useRoute、依赖某个页面级中间件状态——前面提过,渲染错误页时所有中间件会再跑一遍,但布局、页面级 definePageMeta 都不会生效。错误页应该尽量自包含:只展示状态码、信息、一个「返回首页」按钮。
41-10
throw createError 是「主动抛」,常写在 await useFetch 之后判断数据是否为空。onErrorCaptured 是「被动接」,写在某父组件的 setup 里接住子组件冒上来的错。两者配合:页面主动抛 404,全局又用 vue:error 兜住所有漏网的,形成双层保险。
还有一点:createError 的 statusCode 会决定 HTTP 响应状态码(服务端渲染时)和错误页的展示。404、500 这些常见码直接用;自定义业务逻辑错误尽量映射到合适的标准码,方便监控平台聚合统计。客户端用 showError 也能触发全屏页,但官方更推荐 throw createError,因为它能带着上下文一起抛出,定位问题更方便,也更容易在错误页里展示准确信息。
41-11
用 createError 抛错、app/error.vue 定制全屏错误页、clearError 消除错误;局部用 <NuxtErrorBoundary> 或 onErrorCaptured;全局上报放插件里。下一章我们看怎么让你的网站被搜索引擎和社交平台读懂:SEO 与元信息。
41-7 错误监控与上报
生产环境里的错误不能只靠用户反馈来发现。建立一套错误监控机制,能让你在用户投诉之前就知道问题存在。常见的做法是在 app:error 钩子里把错误信息上报到监控平台,如 Sentry、LogRocket 或自建的服务。
上报时应该包含足够的上下文信息:错误消息、堆栈跟踪、发生时间、用户 ID(脱敏)、当前路由等。这些信息能帮你快速定位问题。但要避免上报敏感数据,如密码、令牌、个人身份信息。
除了运行时错误,还应该关注 HTTP 错误率。如果某个 API 路由的 500 错误突然增多,通常意味着服务端出了问题。Nuxt 的服务端中间件可以记录每个请求的状态码,配合日志系统做统计分析。
41-8 全局错误与局部错误的处理策略
Nuxt 里的错误分两种:全局错误(导致整个页面无法渲染)和局部错误(只影响页面的某个部分)。两种错误需要不同的处理策略。
全局错误由 Nuxt 的错误处理机制统一接管,最终展示 error.vue 里定义的错误页面。你可以在这里提供返回首页的链接、搜索框、或者联系客服的入口,帮助用户走出困境。
局部错误则应该在组件内部处理。用 Vue 的 onErrorCaptured 钩子捕获子组件的错误,显示一个友好的占位内容而不是让整个页面崩溃。比如一个数据加载失败的卡片组件,可以显示”加载失败,点击重试”,而不是让整个页面白屏。