上线后的Vue项目难免会出现各种运行时错误,如果不做全局监控,排查问题往往依赖用户反馈或测试重现。在项目中集成一套全局错误监测与日志记录机制,可以将常见的JS错误、静态资源加载失败、Vue渲染异常、请求错误以及Promise未捕获错误统一捕获,并存储到localStorage中。这样开发人员只要查看错误日志就能快速定位问题,大幅降低维护成本。
本文基于Vue3环境,完整实现一个命名为“watchError”的工具模块,包含错误码定义、错误处理函数、自动监听与落地方案。
一、准备工作
1. 错误码规定
使用Map定义一套自定义错误码,与请求状态码类似,便于区分错误类型:- // 错误代码
- const errCode = new Map([
- ['E1001', '系统未知错误'],
- ['E1002', 'vue逻辑错误'],
- ['E1003', 'JavaScript错误'],
- ['E1004', '静态资源加载错误'],
- ['E1005', '请求错误'],
- ['E1006', 'Promise错误']
- ])
复制代码 2. 错误处理函数
export导出一个errorHandler函数,供后续手动调用(比如在Promise.catch或axios响应拦截器中)。该函数接收错误码、错误消息和可选的错误文件路径,内部调用来保存日志:- export const errorHandler = (code: string, msg: string, file = 'null') => {
- saveLog({
- code: code,
- type: errCode.get(`$[code]
- `),
- msg: msg,
- router: router.currentRoute.value.fullPath,
- file: file,
- createTime: new Date().toLocaleString()
- })
- }
复制代码 3. 保存错误日志到localStorage
定义saveLog函数,将错误信息存入localStorage的“ERROR”字段,并限制最多保存50条,超出时替换最旧的一条。通过createTime排序保证后来者替换最早错误:- type errorParams = {
- code: string
- msg: string
- router: string
- file?: string
- createTime: string
- type?: string
- }
- const saveLog = (data: errorParams): void => {
- const nowData = localStorage.getItem('ERROR')
- if (nowData) {
- const allData = JSON.parse(nowData)
- sortArray(allData)
- if (allData.length > 50) {
- allData[0] = data
- sortArray(allData)
- } else {
- allData.push(data)
- }
- localStorage.setItem('ERROR', JSON.stringify(allData))
- } else {
- localStorage.setItem('ERROR', JSON.stringify([data]))
- }
- }
- const sortArray = (allData: string[]) => {
- allData.sort((a: any, b: any) => {
- if (a.createTime > b.createTime) return 1
- return -1
- })
- }
复制代码 二、监听错误
项目上线后主要有四类错误需要捕获。利用Vue官方提供的app.config.errorHandler和window.addEventListener实现。
1. JS错误与静态资源加载错误
通过window的error事件统一监听,利用error.message是否存在来区分:- window.addEventListener('error', (error: any) => {
- if (error.message) {
- // JS错误
- console.error('监测到E1003错误');
- errorHandler('E1003', error.message, error.filename)
- } else {
- // 静态资源加载错误
- console.error('监测到E1004错误');
- errorHandler('E1004', error.target.currentSrc, error.filename)
- }
- }, true)
复制代码 注意:第三个参数为true,表示在捕获阶段监听,确保资源加载错误能被捕获。
2. Vue逻辑错误
利用app.config.errorHandler,它会在组件渲染、计算属性、侦听器等过程中捕获未处理的错误:- app.config.errorHandler = (err: any) => {
- console.error('监测到E1002错误');
- errorHandler('E1002', err.name + ':' + err.message)
- }
复制代码 3. 请求错误与Promise错误
这两种错误需要开发者在使用时主动调用errorHandler,因为它们本身已有自己的错误处理机制。
- 请求错误:在axios响应拦截器中调用errorHandler,传入错误码E1005和错误详情。
- Promise错误:在catch块中调用errorHandler,传入错误码E1006。- // 请求错误示例(在axios.interceptors.response内)
- errorHandler('E1005', `请求地址:${error.config.method}:${error.config.baseURL}/${error.config.url}`)
- // Promise错误示例
- errorHandler('E1006', '测试Promise错误')
复制代码 三、完整代码与使用方法
将上述逻辑整合到一个文件中,例如src/utils/watchError.ts。然后在main.ts中引入并启动:- // main.ts
- import { createApp } from 'vue'
- import { createPinia } from 'pinia'
- import { watchError } from './utils/watchError'
- import App from './App.vue'
- import router from './router'
- const app = createApp(App)
- app.use(createPinia())
- app.use(router)
- app.mount('#app')
- watchError(app)
复制代码 watchError函数接收app实例,内部同时注册Vue错误处理器和全局error事件:- export const watchError = (app: any) => {
- app.config.errorHandler = (err: any) => {
- console.error('监测到E1002错误');
- errorHandler('E1002', err.name + ':' + err.message)
- }
- window.addEventListener('error', (error: any) => {
- if (error.message) {
- console.error('监测到E1003错误');
- errorHandler('E1003', error.message, error.filename)
- } else {
- console.error('监测到E1004错误');
- errorHandler('E1004', error.target.currentSrc, error.filename)
- }
- }, true)
- }
复制代码 使用时,对于axios请求错误和Promise.catch,手动引入errorHandler并调用。
错误日志会存储在localStorage的“ERROR”字段中,你可以开发一个管理页面(如表格)展示这些日志,方便线上排查。
四、总结
以上方案基于Vue3,通用性较强。通过自定义错误码、统一捕获策略与localStorage持久化,能够覆盖绝大多数线上运行时错误。实际项目中可根据需要扩展errorHandler逻辑,比如发送到服务器告警。需要注意的是,window.onerror和app.config.errorHandler都不能捕获所有异常(如异步代码内部未显式reject的情况),建议结合Promise错误手动处理。此方案已在个人项目中验证有效,可作为错误监控的基础模块。 |