首页 > 其他分享 >你是怎么处理vue项目中的错误的?

你是怎么处理vue项目中的错误的?

时间:2024-05-14 19:32:59浏览次数:16  
标签:info vue 错误 err 处理 钩子 vm errorCaptured

一、错误类型

任何一个框架,对于错误的处理都是一种必备的能力

Vue 中,则是定义了一套对应的错误处理规则给到使用者,且在源代码级别,对部分必要的过程做了一定的错误处理。

主要的错误来源包括:

  • 后端接口错误
  • 代码中本身逻辑错误

二、如何处理

后端接口错误

通过axiosinterceptor实现网络请求的response先进行一层拦截

apiClient.interceptors.response.use(
  response => {
    return response;
  },
  error => {
    if (error.response.status == 401) {
      router.push({ name: "Login" });
    } else {
      message.error("出错了");
      return Promise.reject(error);
    }
  }
);

代码逻辑问题

全局设置错误处理

设置全局错误处理函数

Vue.config.errorHandler = function (err, vm, info) {
  // handle error
  // `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
  // 只在 2.2.0+ 可用
}

errorHandler指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例

不过值得注意的是,在不同Vue 版本中,该全局 API 作用的范围会有所不同:

从 2.2.0 起,这个钩子也会捕获组件生命周期钩子里的错误。同样的,当这个钩子是 undefined 时,被捕获的错误会通过 console.error 输出而避免应用崩

从 2.4.0 起,这个钩子也会捕获 Vue 自定义事件处理函数内部的错误了

从 2.6.0 起,这个钩子也会捕获 v-on DOM 监听器内部抛出的错误。另外,如果任何被覆盖的钩子或处理函数返回一个 Promise 链 (例如 async 函数),则来自其 Promise 链的错误也会被处理

生命周期钩子

errorCaptured是 2.5.0 新增的一个生命钩子函数,当捕获到一个来自子孙组件的错误时被调用

基本类型

(err: Error, vm: Component, info: string) => ?boolean

此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播

参考官网,错误传播规则如下:

  • 默认情况下,如果全局的 config.errorHandler 被定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报
  • 如果一个组件的继承或父级从属链路中存在多个 errorCaptured 钩子,则它们将会被相同的错误逐个唤起。
  • 如果此 errorCaptured 钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的 config.errorHandler
  • 一个 errorCaptured 钩子能够返回 false 以阻止错误继续向上传播。本质上是说“这个错误已经被搞定了且应该被忽略”。它会阻止其它任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler

下面来看个例子

定义一个父组件cat

Vue.component('cat', {
    template:`
        <div>
			<h1>Cat: </h1>
        	<slot></slot>
        </div>`,
    props:{
        name:{
            required:true,
            type:String
        }
    },
    errorCaptured(err,vm,info) {
        console.log(`cat EC: ${err.toString()}\ninfo: ${info}`); 
        return false;
    }

});

定义一个子组件kitten,其中dontexist()并没有定义,存在错误

Vue.component('kitten', {
    template:'<div><h1>Kitten: {{ dontexist() }}</h1></div>',
    props:{
        name:{
            required:true,
            type:String
        }
    }
});

页面中使用组件

<div id="app" v-cloak>
    <cat name="my cat">
        <kitten></kitten>
    </cat>
</div>

在父组件的errorCaptured则能够捕获到信息

cat EC: TypeError: dontexist is not a function
info: render

三、源码分析

异常处理源码

源码位置:/src/core/util/error.js

// Vue 全局配置,也就是上面的Vue.config
import config from '../config'
import { warn } from './debug'
// 判断环境
import { inBrowser, inWeex } from './env'
// 判断是否是Promise,通过val.then === 'function' && val.catch === 'function', val !=== null && val !== undefined
import { isPromise } from 'shared/util'
// 当错误函数处理错误时,停用deps跟踪以避免可能出现的infinite rendering
// 解决以下出现的问题https://github.com/vuejs/vuex/issues/1505的问题
import { pushTarget, popTarget } from '../observer/dep'

export function handleError (err: Error, vm: any, info: string) {
    // Deactivate deps tracking while processing error handler to avoid possible infinite rendering.
    pushTarget()
    try {
        // vm指当前报错的组件实例
        if (vm) {
            let cur = vm
            // 首先获取到报错的组件,之后递归查找当前组件的父组件,依次调用errorCaptured 方法。
            // 在遍历调用完所有 errorCaptured 方法、或 errorCaptured 方法有报错时,调用 globalHandleError 方法
            while ((cur = cur.$parent)) {
                const hooks = cur.$options.errorCaptured
                // 判断是否存在errorCaptured钩子函数
                if (hooks) {
                    // 选项合并的策略,钩子函数会被保存在一个数组中
                    for (let i = 0; i < hooks.length; i++) {
                        // 如果errorCaptured 钩子执行自身抛出了错误,
                        // 则用try{}catch{}捕获错误,将这个新错误和原本被捕获的错误都会发送给全局的config.errorHandler
                        // 调用globalHandleError方法
                        try {
                            // 当前errorCaptured执行,根据返回是否是false值
                            // 是false,capture = true,阻止其它任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler
                            // 是true capture = fale,组件的继承或父级从属链路中存在的多个 errorCaptured 钩子,会被相同的错误逐个唤起
                            // 调用对应的钩子函数,处理错误
                            const capture = hooks[i].call(cur, err, vm, info) === false
                            if (capture) return
                        } catch (e) {
                            globalHandleError(e, cur, 'errorCaptured hook')
                        }
                    }
                }
            }
        }
        // 除非禁止错误向上传播,否则都会调用全局的错误处理函数
        globalHandleError(err, vm, info)
    } finally {
        popTarget()
    }
}
// 异步错误处理函数
export function invokeWithErrorHandling (
handler: Function,
 context: any,
 args: null | any[],
    vm: any,
        info: string
        ) {
            let res
            try {
                // 根据参数选择不同的handle执行方式
                res = args ? handler.apply(context, args) : handler.call(context)
                // handle返回结果存在
                // res._isVue an flag to avoid this being observed,如果传入值的_isVue为ture时(即传入的值是Vue实例本身)不会新建observer实例
                // isPromise(res) 判断val.then === 'function' && val.catch === 'function', val !=== null && val !== undefined
                // !res._handled  _handle是Promise 实例的内部变量之一,默认是false,代表onFulfilled,onRejected是否被处理
                if (res && !res._isVue && isPromise(res) && !res._handled) {
                    res.catch(e => handleError(e, vm, info + ` (Promise/async)`))
                    // avoid catch triggering multiple times when nested calls
                    // 避免嵌套调用时catch多次的触发
                    res._handled = true
                }
            } catch (e) {
                // 处理执行错误
                handleError(e, vm, info)
            }
            return res
        }

//全局错误处理
function globalHandleError (err, vm, info) {
    // 获取全局配置,判断是否设置处理函数,默认undefined
    // 已配置
    if (config.errorHandler) {
        // try{}catch{} 住全局错误处理函数
        try {
            // 执行设置的全局错误处理函数,handle error 想干啥就干啥

标签:info,vue,错误,err,处理,钩子,vm,errorCaptured
From: https://www.cnblogs.com/smileZAZ/p/18192059

相关文章

  • vue3 多服务器域名跨域代理和请求配置
    多服务器域名的跨域配置:同样是在vue.config.js文件中对devServer.proxy进行配置,如下:const{defineConfig}=require('@vue/cli-service')module.exports=defineConfig({transpileDependencies:true,lintOnSave:false,//关闭eslint检查,devServer:{......
  • vue给元素添加校验rules
    1.使用validator添加校验规则:在Elemengplus(Vue3版本的ElementPlus)框架中,给el-dialog中的input框添加日期格式验证,可以使用el-form和el-form-item组件来配合实现,并通过el-input组件的v-model绑定数据,结合el-form的验证规则rules实现。以下是一个简单的例子,演示如何给日期输入框......
  • Vue2入门之超详细教程十七-常用内置命令集合
    Vue2入门之超详细教程十四-常用内置指令集合1、简介常用内置指令集合v-bind:单向绑定解析表达式,可简写为:xxxv-model:双向数据绑定v-for:遍历数组/对象/字符串v-on:绑定时间监听,可简写为@v-if:条件渲染(动态控制节点是否存在)v-else:条件渲染(动态控制节点是否存在)v-show:条件渲染......
  • sql server 批量处理孤儿用户
    declare@uservarchar(20)declare@fix_ouvarchar(100)declarec1cursorforselectd.name--,d.sid,s.name,s.sidfromsys.database_principalsdleftjoinsys.server_principalssond.name=s.namewhered.type_desc='SQL_USER'andd.namenotin(......
  • VUE-局部使用
    目录VUE-局部使用快速入门常用指令v-forv-bindv-if&v-showv-onv-modelvue生命周期AxiosVUE-局部使用Vue是一款用于构建用户界面的渐进式的JavaScript框架。(官方:https://cn.vuejs.org/)快速入门准备准备html页面,并引入Vue模块(官方提供)创建Vue程序的应用实例准备元素(......
  • 探索Vue.js:从基础到进阶
    前言随着现代Web应用程序的日益复杂,前端开发框架也在不断演进,为开发者提供更强大、更高效的工具和技术。在这些框架中,Vue.js以其简洁、灵活和响应式的特点而备受青睐。本文将带领读者深入探索Vue.js,从基础概念到进阶技巧,让你全面了解这个令人惊叹的前端开发框架。Vue.js基......
  • 内存溢出问题分析与处理
    内存占用情况查询检查系统内存使用情况以GiB为单位进行显示remotecmd"free-g"1.total:物理内存总量(GiB)。2.used:当前已使用的物理内存量(不包括缓冲区和缓存)(GiB)。3.free:可用的物理内存量(GiB)。4.shared:被多个进程共享的内存量(GiB)。5.buff/cache:作为......
  • springboot+vue创建_1
    Springboot+vue创建一、创建后台项目1.在文件夹创建一个空文件夹,在idea中打开它2.可以先修改一下file-->settings-->Maven里面的一下东西,改成自己的maven地址(以免后面pom.xml文件有问题)3.在sb_vue_mo中右键-->new-->Module,选择SpringInitializer之后自行修改我是选择了ja......
  • vue+element-ui在表格中计算两数差值并让差值>20的字体显示为红色
    <el-table-columnprop="differential"label="差量"class-name="small-paddingfixed-width"><templateslot-scope="scope"><span:c......
  • Jmeter - BeanSell 后置处理器 结合 HttpClient 使用
    背景:在后置处理器中发送POST请求,请求体为JSON数据疑问:1.如果获取Cookie?2.HttpClient怎么发送POST?3.HttpClient怎么添加Cookie?解决:1.如果获取Cookie?importorg.apache.jmeter.protocol.http.control.CookieManager;importorg.apache.jmeter.protocol.http.control.Coo......