最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Vue Suspense 如何在组合式 API 中处理异步组件的加载异常
时间:2026-09-10 13:56:49 编辑:袖梨 来源:一聚教程网
Vue 3 的 Suspense 不捕获加载异常,仅协调等待与就绪状态;异常需通过 errorCaptured、onErrorCaptured 或错误边界处理,fallback 插槽不响应拒绝态,推荐结合 ref 控制错误视图并封装重试逻辑。
Vue 3 的 Suspense 本身不直接捕获或暴露加载异常(比如网络失败、模块解析错误),它只负责协调“等待→就绪”状态。要处理异步组件加载异常,需结合 errorCaptured 钩子、onErrorCaptured 或外层错误边界机制,不能依赖 Suspense 自身的插槽。
异常不会自动显示在 fallback 中
Suspense 的 #fallback 插槽只在“等待中”生效,一旦异步操作被拒绝(reject),组件会停止挂载并抛出错误——此时 fallback 不会渲染,页面可能白屏或报错中断。
- defineAsyncComponent 返回的组件加载失败(如 404、语法错误)→ 触发 unhandled error
- async setup() 中 throw 错误 → 同样中断渲染,不进入 fallback
- 没有内置 error 插槽,也无 onError 回调 API
推荐的异常处理方式
用 errorCaptured 钩子拦截子组件抛出的异步错误,并降级展示友好提示:
- 在父组件中使用
onErrorCaptured(组合式 API)监听子组件错误 - 配合
ref控制是否显示自定义错误视图,替代默认崩溃行为 - 可重试:提供按钮触发
defineAsyncComponent的重新加载逻辑
示例:
<script setup>import { ref, onErrorCaptured } from 'vue'
import { defineAsyncComponent } from 'vue'
const AsyncUser = defineAsyncComponent(() => import('./User.vue'))
const hasError = ref(false)
onErrorCaptured((err) => {
console.error('异步组件加载失败:', err)
hasError.value = true
return false // 阻止向上传播
})
</script>
<template>
<Suspense>
<template #default>
<AsyncUser v-if="!hasError" />
</template>
<template #fallback>
<div class="skeleton">加载中…</div>
</template>
</Suspense>
<div v-if="hasError" class="error-tip">
加载失败,请检查网络或稍后重试
<button @click="hasError = false">重试</button>
</div>
</template>
更健壮的方案:封装带错误处理的异步组件
把错误重试、超时、兜底逻辑封装进自定义 Hook 或工厂函数,避免每个地方重复写 onErrorCaptured:
- 用
defineAsyncComponent({ loader, errorComponent, timeout })(Vue 3.4+ 支持)配置加载超时和错误组件 - 自行封装一个
useAsyncComponent,返回加载状态、错误信息、重试函数 - 路由级统一处理:在
router.beforeEach或布局组件中集中拦截异步组件错误
注意边界情况
某些异常无法被 errorCaptured 捕获,需额外防范:
- 顶层 await 报错(如
const data = await fetch(...))→ 必须在setup()内 try/catch,否则直接崩 - 动态 import 路径错误(如拼写错误)→ 属于模块解析错误,需构建工具层面提示,运行时只能靠
onErrorCaptured拦截 - SSR 环境下 Suspense 行为不同,错误处理逻辑需区分客户端/服务端