Vue Suspense 组件
使用带有 default 和 #fallback 插槽的 、异步组件加载,以及嵌套 Suspense
Vue Suspense 组件 是 CoddyKit 上的免费 Vue Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Vue Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Vue Academy 课程共包含 4 节课。
Suspense 解决什么问题
Suspense 是 Vue 内置的组件,用于协调具有 异步依赖的组件的加载状态。
没有它时,每个异步组件都要管理自己的加载指示器。借助 Suspense,您可以声明一个边界,等待所有嵌套的异步工作完成,并在一切就绪前显示一个统一的 fallback。
两个插槽:默认和 fallback
Suspense 提供两个具名插槽:
- 默认——实际内容,其中可以包含异步组件或异步的
setup() - fallback——默认插槽解析期间要显示的内容
所有异步依赖完成后,Vue 会用默认内容替换 fallback。
<template>
<Suspense>
<template #default>
<UserDashboard />
</template>
<template #fallback>
<div class="spinner">Loading dashboard...</div>
</template>
</Suspense>
</template>异步设置函数作为依赖
当组件的 setup() 函数声明为 async 并等待某项操作时,该组件就会成为异步依赖。Vue 会跟踪返回的承诺。
<script setup> 中的等价写法,是直接在代码块顶层使用 await。
<script setup>
import { ref } from 'vue'
// Top-level await makes this an async dependency of Suspense
const res = await fetch('/api/profile')
const profile = ref(await res.json())
</script>
<template>
<h1>Welcome, {{ profile.name }}</h1>
</template>异步组件也会被跟踪
使用 defineAsyncComponent 创建的组件也会由 Suspense 跟踪。动态的 import() 完成解析前,fallback 会一直显示。
这样,您无需为每个组件单独编写加载界面,也能对大型组件进行代码拆分。
<script setup>
import { defineAsyncComponent } from 'vue'
const Chart = defineAsyncComponent(() =>
import('./HeavyChart.vue')
)
</script>
<template>
<Suspense>
<Chart />
<template #fallback>Preparing chart...</template>
</Suspense>
</template>多个异步子组件共同等待
如果默认插槽包含多个异步依赖,Suspense 会等待所有依赖解析完成后才显示内容。
这样可以避免组件逐个出现导致的布局偏移。
<template>
<Suspense>
<div>
<UserStats /> <!-- async setup -->
<RecentOrders /> <!-- async setup -->
<Recommendations /> <!-- async component -->
</div>
<template #fallback>
<PageSkeleton />
</template>
</Suspense>
</template>使用 onErrorCaptured 捕获拒绝
如果异步 setup() 被拒绝(例如获取数据失败),错误会向上传播到父组件中最近的 onErrorCaptured 钩子。
Suspense 本身不会渲染错误,因此需要将它与错误边界配合使用。
<script setup>
import { ref, onErrorCaptured } from 'vue'
const error = ref(null)
onErrorCaptured((err) => {
error.value = err
return false // stop the error from propagating further
})
</script>错误边界 + 异步挂起模式
生产环境中常见的模式是将 Suspense 包裹在错误边界组件中。onErrorCaptured 返回 false 来停止传播,并改为渲染错误界面。
<script setup>
import { ref, onErrorCaptured } from 'vue'
const err = ref(null)
onErrorCaptured((e) => { err.value = e; return false })
</script>
<template>
<p v-if="err">Failed to load: {{ err.message }}</p>
<Suspense v-else>
<ProfilePanel />
<template #fallback>Loading...</template>
</Suspense>
</template>pending 和 resolve 事件
Suspense 会发出您可以监听的生命周期事件:
- @pending — 进入 pending(loading)状态时触发
- @resolve — 默认插槽完成解析时触发
- @fallback — 显示后备内容时触发
这对于数据分析或进度条很有用。
<template>
<Suspense @pending="onPending" @resolve="onResolve">
<RouteView />
<template #fallback>Loading route...</template>
</Suspense>
</template>timeout 属性:延迟显示后备内容
timeout 属性(以毫秒为单位)会延迟显示后备内容。如果异步操作的解析速度快于超时时间,就不会显示后备内容。
这样可以避免快速响应时加载指示器一闪而过。
<template>
<!-- Only show fallback if loading exceeds 200ms -->
<Suspense :timeout="200">
<FastPanel />
<template #fallback>Loading...</template>
</Suspense>
</template>异步挂起与路由器及过渡效果
Suspense 可以与 RouterView 和 Transition 组合,为异步路由切换添加动画。顺序很重要:Transition 包裹 Suspense,而 Suspense 再包裹路由组件。
<template>
<RouterView v-slot="{ Component }">
<Transition mode="out-in">
<Suspense>
<component :is="Component" />
<template #fallback>Loading page...</template>
</Suspense>
</Transition>
</RouterView>
</template>何时 NOT 使用异步挂起
如果数据会频繁重新获取,而组件始终处于挂载状态,请避免使用 Suspense——它只管理初始异步解析。对于持续的加载状态(分页、重新获取),请改用普通的响应式 loading 引用。
<script setup>
import { ref } from 'vue'
const loading = ref(false)
async function loadMore() {
loading.value = true
await fetchNextPage()
loading.value = false
}
</script>快速检查
检验您对异步挂起的理解。
回顾
您已经学习了 Suspense 如何协调异步依赖:
- 默认插槽容纳异步内容(异步 setup 或异步组件)
- 后备内容插槽在加载期间显示
- 它会等待所有异步子组件完成后才显示内容
- 拒绝会冒泡到父级边界中的
onErrorCaptured timeout可避免加载指示器闪现;@resolve等事件有助于数据分析
用 AI 导师学习 HTML — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 42
- 课程
- 156
常见问题解答
「Vue Suspense 组件」课时是免费的吗?
是的 — 「Vue Suspense 组件」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Vue Academy 课程的其余内容,请升级到 CoddyKit PRO。 Vue Academy 课程共包含 4 节课。
「Vue Suspense 组件」这节课中我会学到什么?
使用带有 default 和 #fallback 插槽的 、异步组件加载,以及嵌套 Suspense 你通过在浏览器中直接运行的动手代码来练习 Vue Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Vue Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Vue Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「Vue Suspense 组件」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Vue Academy 课中编写并运行代码吗?
能。每节 Vue Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。