文章目录
-
- 一、全局错误页面
- 二、针对不同错误码显示不同内容
- 三、捕获异步错误
- 四、手动创建错误
- [五、使用 onErrorCaptured 捕获组件错误](#五、使用 onErrorCaptured 捕获组件错误)
- 六、全局错误处理
- [七、API 错误处理](#七、API 错误处理)
- 八、开发环境显示详细错误
- 总结
写代码最怕什么?不是写不出来,而是写出来后用户一操作就崩了。页面白屏、接口报错、路由找不到......这些问题如果处理不好,用户体验会非常糟糕。今天我们来学习 Nuxt 的错误处理机制,给应用装上"安全气囊"。
一、全局错误页面
当用户访问不存在的页面时,需要展示一个友好的 404 页面。Nuxt 让这件事变得很简单。
创建 error.vue(注意:在项目根目录,不是 pages 目录):
vue
<script setup lang="ts">
const props = defineProps<{
error: {
url: string
statusCode: number
statusMessage: string
message: string
}
}>()
const handleError = () => clearError({ redirect: '/' })
</script>
<template>
<div class="error-page">
<h1>{{ error.statusCode }}</h1>
<p>{{ error.statusMessage || '出错了' }}</p>
<button @click="handleError">返回首页</button>
</div>
</template>
<style scoped>
.error-page {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
text-align: center;
}
h1 {
font-size: 6rem;
color: #00dc82;
margin-bottom: 1rem;
}
p {
font-size: 1.5rem;
color: #666;
margin-bottom: 2rem;
}
button {
padding: 0.75rem 1.5rem;
background: #00dc82;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
}
button:hover {
background: #00b36b;
}
</style>
现在访问一个不存在的路由,比如 /abcdefg,就会显示这个错误页面。
二、针对不同错误码显示不同内容
404、500、403......不同的错误应该有不同的提示。优化一下:
vue
<script setup lang="ts">
const props = defineProps<{
error: {
statusCode: number
message: string
}
}>()
// 根据错误码返回提示信息
const errorInfo = computed(() => {
const errors: Record<number, { title: string; desc: string }> = {
404: { title: '页面走丢了', desc: '您访问的页面不存在' },
403: { title: '禁止访问', desc: '您没有权限访问此页面' },
500: { title: '服务器开小差了', desc: '请稍后再试' }
}
return errors[props.error.statusCode] || {
title: '出错了',
desc: props.error.message
}
})
const goHome = () => clearError({ redirect: '/' })
const goBack = () => clearError()
</script>
<template>
<div class="error-page">
<h1>{{ error.statusCode }}</h1>
<h2>{{ errorInfo.title }}</h2>
<p>{{ errorInfo.desc }}</p>
<div class="actions">
<button @click="goBack">返回上一页</button>
<button class="primary" @click="goHome">返回首页</button>
</div>
</div>
</template>
三、捕获异步错误
页面中的异步操作可能会失败,比如接口请求。用 useAsyncData 或 useFetch 时,错误会自动被 Nuxt 捕获:
vue
<script setup lang="ts">
const { data, error } = await useFetch('/api/articles')
// 如果请求失败,error 会有值
if (error.value) {
// 这里可以处理错误,或者抛出让全局错误页面处理
throw createError({
statusCode: 500,
message: '获取文章列表失败'
})
}
</script>
<template>
<div v-if="data">
<h1>文章列表</h1>
<ul>
<li v-for="article in data" :key="article.id">
{{ article.title }}
</li>
</ul>
</div>
</template>
四、手动创建错误
有时候业务逻辑需要主动抛出错误:
vue
<script setup lang="ts">
const route = useRoute()
const articleId = route.params.id
const { data: article } = await useFetch(`/api/articles/${articleId}`)
// 文章不存在,抛出 404
if (!article.value) {
throw createError({
statusCode: 404,
statusMessage: '文章不存在',
fatal: true // 致命错误,直接显示错误页面
})
}
</script>
createError 的参数:
statusCode: HTTP 状态码statusMessage: 状态消息message: 详细错误信息fatal: 是否致命(致命错误会直接跳错误页面)
五、使用 onErrorCaptured 捕获组件错误
在组件中捕获子组件的错误:
vue
<script setup lang="ts">
const hasError = ref(false)
onErrorCaptured((err) => {
console.error('捕获到错误:', err)
hasError.value = true
return false // 返回 false 阻止错误继续传播
})
</script>
<template>
<div v-if="hasError" class="error-fallback">
<p>组件加载失败</p>
<button @click="hasError = false">重试</button>
</div>
<ChildComponent v-else />
</template>
六、全局错误处理
在插件中设置全局错误处理器:
创建 plugins/error-handler.ts:
ts
export default defineNuxtPlugin((nuxtApp) => {
// 捕获 Vue 错误
nuxtApp.hook('vue:error', (error, instance, info) => {
console.error('Vue Error:', error)
// 可以上报到错误监控平台
// reportError(error)
})
// 捕获服务端错误
nuxtApp.hook('app:error', (error) => {
console.error('App Error:', error)
})
})
七、API 错误处理
如果你的 Nuxt 项目有 API 路由(server/api),也需要处理错误:
ts
// server/api/articles/[id].ts
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id')
// 参数校验
if (!id || !/^\d+$/.test(id)) {
throw createError({
statusCode: 400,
statusMessage: 'Invalid article ID'
})
}
const article = await getArticleById(Number(id))
// 资源不存在
if (!article) {
throw createError({
statusCode: 404,
statusMessage: 'Article not found'
})
}
return article
})
八、开发环境显示详细错误
开发时需要看到详细的错误堆栈,但生产环境不应该暴露。Nuxt 默认就帮你处理好了:
- 开发环境:显示完整错误信息和堆栈
- 生产环境:只显示状态码和简单提示
你也可以在 nuxt.config.ts 中自定义:
ts
export default defineNuxtConfig({
// 开启 nitro 错误处理
nitro: {
errorHandler: '~/error-handler.ts'
}
})
总结
错误处理是保证应用健壮性的关键:
| 场景 | 处理方式 |
|---|---|
| 页面不存在 | error.vue |
| 接口失败 | useFetch 的 error 状态 |
| 业务错误 | createError() |
| 组件错误 | onErrorCaptured |
| 全局错误 | 插件中 hook |
记住:永远不要让用户看到白屏或报错弹窗,给每个可能的错误都准备好兜底方案。
下一篇文章,我们聊聊数据获取,看看 Nuxt 怎么帮你优雅地请求接口。
相关阅读
内容有帮助?点赞、在看、分享三连!评论区等你 💪