Appearance
vue之api-生命周期钩子errorCaptured(Vue2.x)和onErrorCaptured(Vue3.x)
1、认识
👉 errorCaptured(Vue2.5+版本新增)
vue之中的生命周期钩子,用于捕获子组件中的错误。它在组件树中向上冒泡,允许父组件处理子组件抛出的错误。
👉 onErrorCaptured(Vue3.x版本)
在Vue3.x版本中,errorCaptured被重命名为onErrorCaptured
errorCaptured在vue2.5以后的版本之中才有!!!
☞ 介绍
简单概括一下就是可以拿来给我们捕获错误,给用户提示用户信息,然后防止程序崩溃!
☞ 语法
errorCaptured返回一个布尔值(true|false)
true => 错误将不会继续向上传递,相当于它拦截了
false=> 错误继续传播
☞ 使用
比如我们在父组件之中使用了一个子组件ChildComponent,这个时候想要捕获这个组件的错误,然后再父组件进行提示就可以用到errorCaptured
2、errorCaptured-vue2使用
☞ 使用
JS
<template>
<div>
<ChildComponent />
</div>
</template>
<script>
export default {
errorCaptured(err, vm, info) {
// 处理错误
console.error('捕获到的错误:', err);
// 可以返回 true 来阻止向上冒泡
return false;
}
};
</script>
需要额外注意的就是:errorCaptured 只捕获子组件错误,不能捕获父组件错误。
3、onErrorCaptured-vue3使用
☞参数说明
err:捕获到的错误对象。
instance:发生错误的组件实例。
info:包含错误发生位置的附加信息,例如 onErrorCaptured 钩子的调用栈
父组件
JS
<template>
<div>
<ChildComponent />
</div>
</template>
<script>
import { defineComponent, onErrorCaptured } from 'vue';
export default defineComponent({
setup() {
onErrorCaptured((err, instance, info) => {
console.error('捕获到的错误:', err);
console.log('错误发生在组件:', instance);
console.log('错误信息:', info);
// 返回 true 阻止错误继续向上传递
return false; // 可以选择继续传播错误
});
}
});
</script>
子组件
在组件抛出错误给父组件,让他处理
JS
<template>
<div>
<button @click="throwError">抛出错误</button>
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const throwError = () => {
throw new Error('这是一个错误');
};
return { throwError };
}
});
</script>
4、onErrorCaptured源码
之前有个朋友问我为什么只有vue3-onErrorCaptured的手写原理,但是却没有vue2-errorCaptured的手写原理,因为毕竟精力有限,而且官方不维护Vue2,所以深度的研究Vue2已经没有太大的左右,所以只是研究Vue3 之中源码的原理。
☞ 接下来我们就看一下 onErrorCaptured源码,方便我们进行理解
onErrorCaptured 机制比我们之前写的其他的部分都要简单的多
onErrorCaptured主要传入三个参数:(错误、组件实例、错误信息)
JS
// 自定义 error captured 逻辑
const onErrorCaptured = (err, instance, info) => {
console.error('手动捕获的错误:', err);
console.log('发生错误的组件实例:', instance);
console.log('错误信息:', info);
// 返回 false 表示错误未被处理
return false;
};
//使用的时候
onErrorCaptured(new Error('Simulated Error'), null, 'child component');
☞ 接下来我们手写一个简化版的框架使用 onErrorCaptured,然后尝试一下使用onErrorCaptured,这部分学习起来有些晦涩,也可以跳过这部分的理解暂时
- 基本结构
这里面其实是模拟了一下Vue的Component组件,整个过程:
addChild()添加子组件
render()渲染组件
返回创建组件
渲染父组件
渲染子组件
拿到父组件中的onErrorCaptured钩子抛出的错误(错误来自于子组件)
JS
class Component {
constructor(options) {
this.options = options;
this.parent = null;
this.children = [];
}
// 添加子组件
addChild(child) {
this.children.push(child);
child.parent = this;
}
// 渲染组件
render() {
if (this.options.render) {
try {
this.options.render();
} catch (err) {
// 捕获错误并处理
if (this.options.onErrorCaptured) {
// 如果父组件定义了 onErrorCaptured 钩子,就调用它
const handled = this.options.onErrorCaptured(err, this, 'render');
if (!handled) {
// 如果错误没有被处理,继续向上抛出
if (this.parent) {
this.parent.render();
} else {
console.error('Unhandled error:', err);
}
}
} else {
console.error('Error caught in render:', err);
}
}
}
// 递归渲染子组件
this.children.forEach(child => child.render());
}
}
function createComponent(options) {
return new Component(options);
}
// 模拟 Vue 的 `onErrorCaptured` 行为
- 示例组件
JS
// 父组件
const ParentComponent = createComponent({
render() {
console.log('Parent render');
// 假设子组件抛出错误
childComponent.render();
},
onErrorCaptured(err, instance, info) {
console.log('捕获到错误:', err);
console.log('发生错误的组件:', instance);
console.log('错误信息:', info);
// 处理错误并阻止错误继续传播
return true; // 返回 true,表示错误已处理
}
});
// 子组件
const childComponent = createComponent({
render() {
console.log('Child render');
// 抛出一个错误
throw new Error('Child component error!');
}
});
// 将子组件添加到父组件
ParentComponent.addChild(childComponent);
// 渲染父组件
ParentComponent.render();