
一、为什么必须做 Vue 全局错误处理在实际项目开发中我们经常遇到这些问题每个接口、每个函数都写 try/catch代码臃肿重复错误提示散落在各个组件风格不统一、难以收敛线上异常无法统一上报出问题难以定位登录过期、权限不足等通用逻辑无法集中处理全局错误处理的核心价值解耦业务与错误业务代码只关心正常流程错误统一收口统一异常策略提示、跳转、重试、上报全局控制提供监控入口所有错误集中收集便于线上复盘与优化提升用户体验异常不崩溃、不白屏、友好提示二、Vue3 基础官方全局错误入口Vue3 提供了标准的全局错误捕获配置app.config.errorHandler它是整个体系的基石。2.1 基础使用// main.js import { createApp } from vue import App from ./App.vue const app createApp(App) // 全局错误捕获 app.config.errorHandler (err, instance, info) { console.error(全局捕获到异常, err, instance, info) } app.mount(#app)2.2 它能捕获哪些错误组件 setup /render 函数内同步错误生命周期钩子onMounted、onUpdated 等抛出错误模板渲染、指令执行异常watch /computed 中抛出的错误Vue 管理的 Promise 链错误2.3 它不能捕获哪些错误setTimeout /setInterval 内抛出的错误原生 fetch/axios 未捕获的 Promise Reject主动 new Promise ().reject () 且未 catch页面资源加载失败img/script/css 4042.4 参数说明app.config.errorHandler (err, instance, info) { // err错误对象message、stack // instance报错组件实例可拿到 props、data等 // info错误来源信息如render、watch、lifecycle hook、function }三、工程化第一步定义可识别的业务错误要实现优雅处理必须先标准化错误结构而不是只抛字符串。// src/constants/errorTypes.js export class BusinessError extends Error { constructor(message, code, data null) { super(message) this.code code this.data data this.isBusinessError true this.name BusinessError } } // 登录过期 export class AuthExpiredError extends BusinessError { constructor(message 登录已过期请重新登录) { super(message, AUTH_EXPIRED) } } // 权限不足 export class PermissionDeniedError extends BusinessError { constructor(message 您没有此操作权限) { super(message, PERMISSION_DENIED) } } // 业务校验失败 export class ValidateError extends BusinessError { constructor(message 数据校验不通过, data) { super(message, VALIDATE_FAILED, data) } }这样在业务中抛出的错误全局层就能精准识别类型。四、工程化第二步全局错误分类处理统一入口 策略分发避免一堆 if else。4.1 错误处理策略表最优雅写法// src/utils/errorHandler.js import { ElMessage } from element-plus import router from /router import { reportError } from ./errorReport // 错误策略表 const errorStrategy { // 登录过期 AUTH_EXPIRED: (err) { ElMessage.warning(err.message) router.push(/login) }, // 权限不足 PERMISSION_DENIED: (err) { ElMessage.error(err.message) }, // 校验失败 VALIDATE_FAILED: (err) { ElMessage.info(err.message) }, // 默认兜底 default: (err) { ElMessage.error(系统异常请稍后重试) reportError(err) // 上报监控 } } export function registerGlobalError(app) { app.config.errorHandler (err, instance, info) { console.error([全局错误], err, instance, info) // 附加错误上下文 err.context { component: instance?.$options?.name || instance?.type?.name || unknown, trigger: info } // 策略匹配执行 const handler errorStrategy[err.code] || errorStrategy.default handler(err) } }4.2 在 main.js 注册import { createApp } from vue import App from ./App.vue import { registerGlobalError } from /utils/errorHandler const app createApp(App) registerGlobalError(app) app.mount(#app)五、补齐短板捕获 Promise 与异步错误errorHandler不捕获原生 Promise我们用全局事件补齐。// src/utils/errorHandler.js export function registerPromiseErrorHandler(app) { // 全局未捕获的 Promise Reject window.addEventListener(unhandledrejection, (event) { event.preventDefault() // 阻止浏览器默认提示 const err event.reason // 抛给 Vue 全局错误处理统一消化 app.config.errorHandler(err, null, unhandledRejection) }) }在 main.js 同时注册registerGlobalError(app) registerPromiseErrorHandler(app)这样axios/fetch 错误、定时器错误、异步异常全部能捕获。六、必备能力错误上报与监控线上项目必须可观测上报错误堆栈、环境、用户信息。// src/utils/errorReport.js export function reportError(err) { const data { message: err.message, code: err.code, stack: err.stack?.substring(0, 500), // 堆栈过长截取 component: err.context?.component, trigger: err.context?.trigger, url: location.href, ua: navigator.userAgent, time: new Date().toISOString() } // 上报后端 fetch(/api/error/report, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify(data) }).catch(() {}) }七、与 Axios 结合接口错误统一收口把接口异常也纳入全局体系业务完全零感知。// src/utils/request.js import axios from axios import { AuthExpiredError, PermissionDeniedError } from /constants/errorTypes const service axios.create({ baseURL: /api }) service.interceptors.response.use( (res) res.data, (error) { const status error.response?.status if (status 401) { return Promise.reject(new AuthExpiredError()) } if (status 403) { return Promise.reject(new PermissionDeniedError()) } return Promise.reject(error) } ) export default service业务代码彻底清爽const fetchData async () { const data await api.getUserList() // 无需try/catch list.value data }八、最终效果业务与错误完全解耦业务组件只写核心逻辑script setup import api from /utils/request import { onMounted } from vue const list ref([]) onMounted(async () { const data await api.getList() list.value data }) /script所有异常401 → 自动跳登录403 → 自动提示无权限其他 → 统一提示 自动上报业务代码完全干净九、总结一套完整的 Vue 全局错误体系包括统一入口app.config.errorHandler标准错误类型BusinessError 及其子类策略分发策略表模式易扩展、易维护全覆盖捕获errorHandler unhandledrejection统一提示与跳转体验一致统一上报线上可监控、可复盘最终实现业务代码只管业务错误交给全局架构清晰、长期不腐化。