Vue虽无原生ErrorBoundary,但可通过errorCaptured钩子拦截子组件渲染/生命周期错误,配合hasError状态与条件渲染实现错误隔离和兜底UI;注意其不捕获异步错误,需额外处理。

Vue 本身没有像 React 那样的原生 ErrorBoundary 组件,但可以通过组合 errorCaptured 钩子、状态降级、条件渲染和合理的错误兜底策略,实现类错误边界的效果——即隔离异常组件、防止错误扩散、维持页面其他部分正常运行,并给出友好反馈。
errorCaptured 是核心入口
它不是“捕获后自动修复”,而是提供一个拦截点,让你决定是否让错误继续冒泡、是否展示替代 UI、是否上报日志。
- 它在子组件抛出渲染错误、生命周期钩子错误或 watcher 错误时触发;
- 接收三个参数:
err(错误对象)、instance(出错的子组件实例)、info(错误来源,如"render function"或"mounted hook"); -
必须显式返回
false才能阻止错误向上传播,否则父组件仍会收到该错误(甚至触发全局errorHandler)。
export default {
name: 'DashboardCard',
errorCaptured(err, instance, info) {
console.warn('子组件异常被捕获:', err, info)
this.hasError = true
// 可选:上报错误(如 Sentry)
// Sentry.captureException(err, { extra: { component: instance.$options.name } })
return false // 关键:阻断冒泡
},
data() {
return { hasError: false }
},
render() {
if (this.hasError) {
return <div class="error-placeholder">⚠️ 数据加载失败,请刷新重试</div>
}
return <ActualContent />
}
}错误状态需配合条件渲染
仅拦截错误不够,还要让用户感知不到崩溃。常见做法是:
- 在
data或ref中定义hasError: false; -
errorCaptured中设为true,并清空可能出错的数据(如this.items = []); - 模板中用
v-if="!hasError"渲染主内容,v-else显示兜底提示或重试按钮; - 可搭配
v-show实现平滑过渡,避免 DOM 销毁重建。
注意异步错误不触发 errorCaptured
errorCaptured 只捕获同步渲染路径中的错误(如模板求值、setup() 同步执行、mounted 钩子等)。
立即学习“前端免费学习笔记(深入)”;
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
-
Promise.reject()、setTimeout(() => { throw new Error() })等异步错误不会触发它; - 这类错误需靠
try/catch+async/await、Axios 响应拦截器、或全局unhandledrejection监听来处理; - 若异步逻辑在组件内发起,建议在
catch块中手动设hasError = true,保持 UI 一致性。
父组件可统一包装“可容错区域”
对一组可能出错的子组件,可用高阶封装组件统一管理错误状态:
<template>
<slot v-if="!isErrored"></slot>
<div v-else class="fallback" @click="retry">
<slot name="fallback">加载失败</slot>
<button>重试</button>
</div>
</template>
<script>
export default {
name: 'SafeZone',
props: { autoRetry: { type: Boolean, default: true } },
data() {
return { isErrored: false }
},
errorCaptured(err, instance, info) {
this.isErrored = true
return false
},
methods: {
retry() {
this.isErrored = false
// 触发子组件重新初始化(如 emit event 或 forceUpdate)
this.$emit('retry')
}
}
}
</script>使用时:
<SafeZone @retry="loadData"> <UserList /> <ChartPanel /> </SafeZone>
不要忽略资源加载失败
模板中 <img>、<iframe>、<video> 的加载失败不会触发 errorCaptured,需单独监听:
-
<img :src="avatar" @error="onImageError" /> -
<iframe @error="onIframeError" /> - 在对应 handler 中设
hasError = true或切换占位图。
基本上就这些。关键不在“捕获一切”,而在于明确哪些错误可恢复、哪些需降级、哪些该上报——有意识地分层防御,比堆砌 try/catch 更优雅。

















