1. 基本功能
<Suspense>
是 Vue 3 中引入的一个内置组件,用于处理异步组件和异步数据加载。它允许在异步内容加载完成之前显示备用内容(如加载动画或占位符),从而提升用户体验。
2. 基本用法
包裹异步组件:
<template> <Suspense> <template #default> <AsyncComponent /> </template> <template #fallback> <div>Loading...</div> </template> </Suspense> </template> <script setup> import { defineAsyncComponent } from 'vue'; const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue')); </script>
在这个例子中,当
AsyncComponent
加载时,#fallback
插槽的内容会显示,加载完成后,#default
插槽的内容会渲染。结合
async setup
使用:<template> <Suspense> <template #default> <UserProfile /> </template> <template #fallback> <div>Loading user data...</div> </template> </Suspense> </template> <script> import { ref } from 'vue'; const UserProfile = { async setup() { const user = ref(null); const fetchUser = () => { return new Promise((resolve) => { setTimeout(() => { resolve({ name: 'John Doe', age: 30 }); }, 2000); }); }; user.value = await fetchUser(); return { user }; }, template: ` <div> <h1>User Profile</h1> <p>Name: {{ user.name }}</p> <p>Age: {{ user.age }}</p> </div> `, }; export default { components: { UserProfile }, }; </script>
在这个例子中,
UserProfile
组件的setup
函数是异步的,模拟了一个数据请求。在数据加载完成之前,#fallback
插槽的内容会显示。
3. 性能优化
- 避免白屏:通过在异步组件加载时显示备用内容,避免页面空白,提升用户体验。
- 组合式 API 的
useSuspense
hook:Vue 团队正在推进组合式 API 的useSuspense
hook,以进一步优化异步组件的使用。
4. 局限性与替代方案
- 仅支持
setup()
返回 Promise:<Suspense>
只能用于setup()
返回 Promise 的场景,不能用于普通的异步请求,如onMounted()
之后的异步请求。 - 替代方案:对于普通异步请求,可以使用
v-if
或loading 状态
来控制组件的渲染。
5. 最佳实践
- 简单场景优先使用
<Suspense>
:在简单的异步组件加载场景中,优先使用<Suspense>
来提升用户体验。 - 复杂异步流组合使用:在复杂的异步流中,可以结合多个
<Suspense>
来处理多个异步依赖。 - 避免常见错误:避免在
<Suspense>
内部使用v-if
,忘记处理边界错误,以及嵌套层级过深。
6. 适用场景
- 异步组件加载:如动态加载组件。
- 异步数据获取:如在
setup()
中获取数据。 - 服务器端渲染(SSR):结合
<Suspense>
提高首屏加载速度和 SEO 体验。
7. 注意事项
- 错误处理:
<Suspense>
本身不提供错误处理机制,但可以通过onErrorCaptured
钩子捕获异步组件加载中的错误。 - 嵌套使用:
<Suspense>
可以嵌套使用,但需要注意每个<Suspense>
的#fallback
内容只会在其直接子组件的异步操作未完成时显示。
通过合理使用 <Suspense>
,可以将异步组件的加载时间转化为提升用户体验的机会,使应用在等待异步操作完成时更加友好和流畅。