<Suspense>
是一个内置组件,它允许你在组件加载时显示一个备用内容(fallback content),直到组件真正渲染完成。这对于处理异步组件加载特别有用,可以提供更好的用户体验,防止用户看到未完成的界面或空白的加载状态。
我们了解Suspense之前,先了解下什么是异步依赖和异步组件。
异步依赖
异步依赖通常指的是在组件加载或执行过程中需要异步获取的数据或功能。这些数据或功能可能来自网络请求、其他组件的异步加载,或者任何其他需要时间的操作。
例如:
<Suspense>
└─ <Dashboard>
├─ <Profile>
│ └─ <FriendStatus>(组件有异步的 setup())
└─ <Content>
├─ <ActivityFeed> (异步组件)
└─ <Stats>(异步组件)
在这个组件树中有多个嵌套组件,要渲染出它们,首先得解析一些异步资源。如果没有 <Suspense>
,则它们每个都需要处理自己的加载、报错和完成状态。在最坏的情况下,我们可能会在页面上看到三个旋转的加载态,在不同的时间显示出内容。
异步组件
异步组件是当需要时才会加载和编译的组件。这意味着应用程序不会在启动时立即加载所有组件,而是在需要时才从服务器请求组件的代码。这可以显著提高首屏加载速度,并减少应用程序的内存占用和带宽消耗。
异步组件通常通过 defineAsyncComponent
函数来定义。这个函数接受一个返回 Promise 的函数作为参数,该 Promise 解析为要加载的组件。例如:
<script setup lang="ts">
import { defineAsyncComponent } from 'vue';
const AsyncComponent = defineAsyncComponent(() =>
import('./AsyncComponent.vue')
);
</script>
在上面的代码中,import('./AsyncComponent.vue')
是一个动态导入表达式,它返回一个 Promise,该 Promise 在组件代码加载完成后解析。defineAsyncComponent
函数使用这个 Promise 来创建一个异步组件。
Suspense 组件
使用场景
1. 异步组件加载
当应用需要加载较大的组件或数据,而用户不需要立即看到这些内容时,可以使用Suspense
组件来包裹这些异步加载的组件。在组件加载完成之前,Suspense
可以展示一个占位内容(通常是一个加载指示器),提供更好的用户体验。
2. 延迟加载和代码拆分
在大型应用中,为了优化性能,通常会使用代码拆分(code splitting)技术将应用拆分成多个小块,按需加载。在这种情况下,Suspense
可以与动态导入(dynamic imports)结合使用,以实现组件的延迟加载。当组件被请求时,它会被异步加载,而Suspense
则负责在加载期间展示占位内容。
3. 平滑的过渡效果
Suspense
不仅提供了占位内容的功能,还可以实现平滑的过渡效果。当异步组件加载完成后,它会自动替换掉占位内容,而不会造成页面的突然变化,从而提升了用户体验。
使用方法:
<Suspense>
组件允许你在异步组件加载时显示备用内容。它有两个插槽:#default
和 #fallback
。#default
插槽用于放置异步组件,而 #fallback
插槽用于在组件加载时显示备用内容。
<template>
<div>
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>加载中...</div>
</template>
<template #error>
<div>加载失败</div>
</template>
</Suspense>
</div>
</template>
<script setup lang="ts">
import { defineAsyncComponent, onMounted, onErrorCaptured } from 'vue';
const AsyncComponent = defineAsyncComponent(() =>
import('./AsyncComponent.vue')
);
onMounted(() => {
// 可以在这里处理组件加载完成后的逻辑
});
onErrorCaptured((err, vm, info) => {
// 可以在这里处理组件加载错误
console.error('Async component loading error:', err);
return false; // 返回 false 表示不阻止错误继续向上冒泡
});
</script>
异步子组件:
<!-- AsyncComponent.vue -->
<template>
<div>
<!-- 组件内容,可能是从服务器获取的数据显示 -->
<p>{{ data }}</p>
</div>
</template>
<script>
export default {
name: 'AsyncComponent',
async setup() {
const { data } = await fetchSomeData(); // 假设 fetchSomeData 是一个异步函数
return { data };
},
};
</script>
在上面的代码中,<Suspense>
组件包含了三个插槽:#default
、#fallback
和 #error
。当 AsyncComponent
正在加载时,会显示 #fallback
插槽的内容(即“加载中...”文本)。如果组件加载成功,#default
插槽的内容会被渲染。如果组件加载失败,你可以使用 #error
插槽来显示错误消息。
注意,
<Suspense>
组件默认不会捕获错误。为了处理异步组件加载时可能出现的错误,你可以使用onErrorCaptured
生命周期钩子。在这个钩子中,你可以记录错误、显示错误消息或执行其他错误处理逻辑。