在Vue 中,则是定义了一套对应的缺点处理规则给到利用者,且在源代码级别,对部分必要的过程做了一定的缺点处理。
紧张的缺点来源包括:
后端接口缺点代码中本身逻辑缺点二、如何处理后端接口缺点通过axios的interceptor实现网络要求的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 functioninfo: render
三、源码剖析
非常处理源码
源码位置:/src/core/util/error.js
// Vue 全局配置,也便是上面的Vue.configimport config from '../config'import { warn } from './debug'// 判断环境import { inBrowser, inWeex } from './env'// 判断是否是Promise,通过val.then === 'function' && val.catch === 'function', val !
=== null && val !== undefinedimport { 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 想干啥就干啥 return config.errorHandler.call(null, err, vm, info) } catch (e) { // 如果开拓者在errorHandler函数中手动抛出同样缺点信息throw err // 判断err信息是否相等,避免log两次 // 如果抛出新的缺点信息throw err Error('你好毒'),将会一起log输出 if (e !== err) { logError(e, null, 'config.errorHandler') } } } // 未配置常规log输出 logError(err, vm, info)}// 缺点输出函数function logError (err, vm, info) { if (process.env.NODE_ENV !== 'production') { warn(`Error in ${info}: "${err.toString()}"`, vm) } / istanbul ignore else / if ((inBrowser || inWeex) && typeof console !== 'undefined') { console.error(err) } else { throw err }}
1、在配置路由并引入组件后,报错:
Unknown custom element: <router-link> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
缺点缘故原由:vue-router没有注册
办理办法:
//注册插件 非常主要,不能忘却
Vue.use(VueRouter)
2、在组件中的标签和样式中图片路径出错时:报错:
Errors while compiling. Reload prevented.
Module not found: Error: Can't resolve './src/assets/img/btn_bg.png' in 'E:\myStudy\vue案例\chexian-spa\src\components'
办理办法:将图片的路径重新书写
3、在组件中标签没有闭合,报错:
Errors while compiling. Reload prevented.
./node_modules/_vue-loader@13.4.0@vue-loader/lib/template-compiler?{"id":"data-v-00822b28","hasScoped":false,"buble":{"transforms":{}}}!./node_modules/_vue-loader@13.4.0@vue-loader/lib/selector.js?type=template&index=0&bustCache!./src/components/BaseProject.vue
(Emitted value instead of an instance of Error)
办理办法:检讨html代码
4、在利用less定义变量是报错:
缺点缘故原由:必须用分号结尾:@imgUrl:'../../assets/img/';
Compiled with problems:
编译问题
C:\myel\src\views\HomeView.vue
缺点涌现文件
3:1 error Mixed spaces and tabs no-mixed-spaces-and-tabs
4:1 error Mixed spaces and tabs no-mixed-spaces-and-tabs
第3行的第一个字符
第4函的第一个字符
Mixed spaces and tabs
缺点缘故原由:稠浊的空格与tab
no-mixed-spaces-and-tabs
缺点规则: no-mixed-spaces-and-tabs 不准混空格与tab
2 problems (2 errors, 0 warnings)
2个问题(2个缺点,0个警告)
Compiled with problems:
编译缺点
ERROR in ./src/views/HomeView.vue?
缺点涌现的位置
Unexpected keyword 'const'. (6:0)
第6行第0个字符有个不应该涌现的关键字 const
63 | const user = reactive({ userid: "", pwd: "", code: "" }), | ^ 64 | const rules = reactive({ | ^ 65 | userid: [
第63到64行两个^之间有缺点
ERROR in ./src/router/index.ts 10:19-57
缺点发生在 ./src/router/index.ts 第10行第19个字符到57字符
Module not found: Error: Can't resolve '../views/admin/AdminVeiw.vue' in 'C:\myel\src\router'
,模块找不的 不能resolve(兑现,创造,办理)../views/admin/AdminVeiw.vue
在C:\myel\src\router
总结:文件../views/admin/AdminVeiw.vue(文件名/路径发生缺点)
本地开拓环境要求做事器接口跨域的问题上面的这个报错大家都不会陌生,报错是说没有访问权限(跨域问题)。本地开拓项目要求做事器接口的时候,由于客户真个同源策略,导致了跨域的问题。
下面先演示一个没有配置许可本地跨域的的情形:
可以看到,此时我们点击获取数据,浏览器提示我们跨域了。以是我们访问不到数据。
那么接下来我们演示设置许可跨域后的数据获取情形:
把稳:配置好后一定要关闭原来的server,重新npm run dev启动项目。不然无效。
把稳:配置好后一定要关闭原来的server,重新npm run dev启动项目。不然无效。
我们在1出设置了许可本地跨域,在2处,要把稳我们访问接口时,写的是/api,此处的/api指代的便是我们要要求的接口域名。如果我们不想每次接口都带上/api,可以变动axios的默认配置axios.defaults.baseURL = '/api';这样,我们要求接口就可以直接this.$axios.get('app.php?m=App&c=Index&a=index'),很大略有木有。此时如果你在network中查看xhr要求,你会创造显示的是localhost:8080/api的要求地址。这样没什么大惊小怪的,代理而已:
给大家分享我网络整理的各种学习资料,前端小白互换、学习互换,也可以直接问我,我会组织大家一起做项目练习,帮助大家匹配一位学习伙伴相互监督学习-下面是学习资料参考。
前端学习互换、自学、学习资料等推举 - 知乎