本文中例子没有采用vue脚手架搭建项目,而是在ts项目中,引入vue进行使用
如果使用脚手架搭建,将代码封装一下,在入口文件中使用vue.use()注册使用即可
引入vue依赖
引入枚举,全局发布订阅器
import Vue from 'vue';
import {progress, thePublicModule} from "./import";
基类
/*
* @Author GyYu
* @Description //TODO 控制台错误信息提取整理
* @Date 11:44 2021/3/20
* @Param
* @return
**/
export default class exceptionCapture {
private debugConfig: any // 常量配置
constructor() {
this.debugConfig = {
scriptVersion: '1.0',
releaseStage: 'pro'
}
this.init(); // 调用初始化,监听vue报错,一般报错
}
private init(): void {
let _self = this;
// 捕获vue的异常信息
Vue.config.errorHandler = function (err, vm, info) {
if (vm) {
let componentName = _self.formatComponentName(vm); // 获取组件名称
let propsData = vm.$options && vm.$options.propsData; // 获取组件propdata
let model = vm.$vnode && vm.$vnode.data; // 获取组件绑定信息
_self.abnormalDataArrangement({
type: 'caught', // 错误信息抓的很全
error: err,
metaData: {
userToken: {userId: 1},
componentName, // 报错组件名称
propsData, // 报错组件注入参数
model,//组件绑定信息
},
message: info,
})
} else {
_self.abnormalDataArrangement({
type: 'uncaught', // 没抓住详细错误信息,只知道报错了
error: err,
metaData: {
userToken: {userId: 1}
},
message: info ? info : '',
})
}
};
// 除了vue外其他异常信息
window.onerror = function (msg, url, lineNo, columnNo, error) {
_self.abnormalDataArrangement({
type: 'caught', // 抓住了
error,
metaData: {
userToken: {userId: 1},
lineNumber: lineNo, // 行号
columnNumber: columnNo, // 列号
fileName: url // 报错文件地址
},
message: msg, // 错误信息
})
}
}
/*
* @Author GyYu
* @Description //TODO 日期格式化
* @Date 12:04 2021/3/20
* @Param
* @return
**/
private dateFormat(fmt, date): string {
date = new Date(date);
let ret;
let opt = {
"Y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"H+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"S+": date.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
}
}
return fmt;
}
/*
* @Author GyYu
* @Description //TODO 获取vue组件实例的基本信息
* @Date 12:04 2021/3/20
**/
private formatComponentName(vm): string {
if (vm.$root === vm) return 'root';
let name = vm._isVue ? (vm.$options && vm.$options.name) || (vm.$options && vm.$options._componentTag) : vm.name;
return (
(name ? 'component <' + name + '>' : 'anonymous component') + (vm._isVue && vm.$options && vm.$options.__file ? ' at ' + (vm.$options && vm.$options.__file) : '')
);
}
/*
* @Author GyYu
* @Description //TODO 异常数据整理 ,有其他需要加的信息,在这里整理, 整理完毕发布
* @Date 13:16 2021/3/20
**/
private abnormalDataArrangement({type = 'caught', error, message, metaData}): void {
let {scriptVersion, releaseStage} = this.debugConfig, // 解构赋值
name = error && error.name || 'error', // 错误信息
stacktrace = error && error.stack || '', // 堆栈信息
title = document.title, // 文档标题
url = window.location.href, // 地址
client = { // 浏览器信息
userAgent: window.navigator.userAgent, //请求的用户代理头的值
height: window.screen.height, // 频幕高度
width: window.screen.width, // 频幕宽度
referrer: window.document.referrer //页面打开方式
},
time = this.dateFormat("YYYY-mm-dd HH:MM:SS", Date.now()), // 当前时间
messages = message || error && error.message || '', // 错误信息头
errType = type // 错误类别, 捕获到详细信息,没有捕获到详细信息 caught 捕获 uncaught 没有捕获到详细信息,就知道报错了
let errorMes = {
scriptVersion, releaseStage, metaData, name, stacktrace, title, url, client, time, messages, errType
}
thePublicModule.event.emit("progress", progress.error, errorMes) // 全局的发布订阅 可用console.log(errorMes)代替
}
}
采集的非vue实例上的信息,如下图
采集的vue实例上的错误信息,如下图