Suspense
Suspense 用于处理异步组件加载时的占位显示。当子组件中包含异步内容(如懒加载组件)时,Suspense 会在加载完成前显示 fallback 内容,加载完成后自动切换为实际内容。
基本用法
tsx
import { Suspense, lazy } from 'vitarx'
// 创建一个懒加载组件
const AsyncChart = lazy(() => import('./Chart'))
function App() {
return (
<Suspense fallback={<div>加载中...</div>}>
<AsyncChart />
</Suspense>
)
}当 AsyncChart 还在加载时,页面会显示"加载中…";加载完成后,自动替换为 AsyncChart 的内容。
属性
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
children | View | 是 | 实际要渲染的内容,通常包含异步组件 |
fallback | View | 否 | 加载中显示的占位视图 |
onResolved | () => void | 否 | 所有异步内容加载完成后的回调函数 |
工作原理
Suspense 内部维护一个计数器,用来追踪子组件中异步任务的数量:
- 当子组件中有异步内容正在加载时,计数器大于 0,显示
fallback - 当所有异步内容加载完成后,计数器归零,自动切换为
children - 如果子组件中没有异步内容,计数器为 0,直接显示
children
这意味着你可以在一个 Suspense 中放置多个异步组件,它会等待所有异步组件都加载完成后才切换。
onResolved 回调
onResolved 会在所有异步子内容加载完成并替换到视图后调用,适合做一些加载完成后的操作,比如隐藏全局 loading、记录日志等。
tsx
import { Suspense, lazy } from 'vitarx'
const AsyncTable = lazy(() => import('./Table'))
const AsyncChart = lazy(() => import('./Chart'))
function Dashboard() {
return (
<Suspense
fallback={<div>数据加载中...</div>}
onResolved={() => {
console.log('所有数据加载完成')
}}
>
<AsyncTable />
<AsyncChart />
</Suspense>
)
}多层嵌套 Suspense
Suspense 支持嵌套使用。内层 Suspense 只负责它自己的异步子组件,外层 Suspense 负责外层的异步子组件。内层 Suspense 完成加载后,外层的计数器才会减少。
tsx
import { Suspense, lazy } from 'vitarx'
const AsyncHeader = lazy(() => import('./Header'))
const AsyncContent = lazy(() => import('./Content'))
const AsyncSidebar = lazy(() => import('./Sidebar'))
function App() {
return (
// 外层 Suspense 等待 AsyncHeader
<Suspense fallback={<div>页面加载中...</div>}>
<AsyncHeader />
{/* 内层 Suspense 等待 AsyncContent 和 AsyncSidebar */}
<Suspense fallback={<div>内容区域加载中...</div>}>
<AsyncContent />
<AsyncSidebar />
</Suspense>
</Suspense>
)
}完整示例
下面是一个完整的示例,展示了 Suspense 配合 lazy 懒加载组件的使用:
tsx
import { Suspense, lazy, ref } from 'vitarx'
// 懒加载组件——在 Suspense 内使用时,无需指定 loading 选项
const UserProfile = lazy(() => import('./UserProfile'))
const UserPosts = lazy(() => import('./UserPosts'))
function UserPage() {
const loaded = ref(false)
return (
<div>
<h1>用户主页</h1>
<Suspense
fallback={<div>页面数据加载中,请稍候...</div>}
onResolved={() => {
loaded.value = true
console.log('用户主页加载完成')
}}
>
<UserProfile userId="123" />
<UserPosts userId="123" />
</Suspense>
</div>
)
}INFO
当 lazy 组件在 Suspense 内使用时,Suspense 的 fallback 优先级高于 lazy 的 loading 选项,因此无需为 lazy 指定 loading。只有在 lazy 组件不在 Suspense 内使用时,loading 选项才会生效。
下一步
- Lazy 与 lazy — 了解懒加载组件的详细用法
- For — 列表渲染
- Freeze — 组件缓存