# Suspense
新增
试验性
Suspense 是一个试验性的新特性并且其 API 可能随时更改。特此声明以便社区能够为当前的实现提供反馈。
它不应该被用在生产环境。
# 介绍
在正确渲染组件之前进行一些异步请求是很常见的事。组件通常会在本地处理这种逻辑,绝大多数情况下这是非常完美的做法。
该 <suspense>
组件提供了另一个方案,允许等待整个组件树处理完毕而不是单个组件。
一个常见的用例是用到了异步组件:
<template>
<suspense>
<template #default>
<todo-list />
</template>
<template #fallback>
<div>
Loading...
</div>
</template>
</suspense>
</template>
<script>
export default {
components: {
TodoList: defineAsyncComponent(() => import('./TodoList.vue'))
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
这个 <suspense>
组件有两个插槽。它们都只接收一个子节点。default
插槽里的节点会尽可能展示出来。如果不能,则展示 fallback
插槽里的节点。
重要的是,异步组件不需要作为 <suspense>
的最近子节点。它可以在组件树任意深度的位置且不需要出现在和 <suspense>
自身相同的模板中。只有所有的后代组件都准备就绪,该内容才会被认为解析完毕。
另一个让后代组件触发 fallback
的方式是从 setup
函数返回一个 Promise。通常这是通过 async
实现的而不是显性地返回一个 Promise:
export default {
async setup() {
// 在 `setup` 内部使用 `await` 需要非常小心
// 因为大多数组合式 API 函数只会在
// 第一个 `await` 之前工作
const data = await loadData()
// 它隐性地包裹在一个 Promise 内
// 因为函数是 `async` 的
return {
// ...
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 子组件更新
一旦 <suspense>
的 default
插槽里的内容被解析,则它只有在 default
根结点被替换的时候才会被再次触发。而树里的深层嵌套组件不足以让 <suspense>
回到等待状态。
如果根结点发生了变化,它会触发 pending
事件。然而默认情况下它不会更新 DOM 以展示 fallback
内容。取而代之的是它会继续展示旧的 DOM 直到新组件准备就绪。这个行为可以通过 timeout
prop 进行控制。这个值是一个毫秒数,告诉 <suspense>
组件多久之后展示 fallback
。如果这个值是 0
则表示它在 <suspense>
进入等待状态时会立即显示。
# 事件
在 pending
事件之外,<suspense>
组件还拥有 resolve
和 fallback
事件。resolve
事件会在 default
插槽完成新内容的解析之后被触发。fallback
事件会在 fallback
插槽的内容展示的时候被触发。
这些事件可以用在诸如当新组件加载时在旧 DOM 上展示一个加载标识等场景。
# 和其它组件结合
将 <suspense>
跟 <transition>
和 <keep-alive>
组件相结合是常见的情形。这些组件的嵌套顺序对于它们的正确工作很重要。
额外的,这些组件经常用于衔接 Vue Router (opens new window) 的 <router-view>
组件。
以下示例展示了如何嵌套这些组件以让它们的表现符合预期。为了简化这个结合你可以移除不需要的组件:
<router-view v-slot="{ Component }">
<template v-if="Component">
<transition mode="out-in">
<keep-alive>
<suspense>
<component :is="Component"></component>
<template #fallback>
<div>
Loading...
</div>
</template>
</suspense>
</keep-alive>
</transition>
</template>
</router-view>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Vue Router 有内置的基于动态导入的组件懒加载 (opens new window)支持。它和异步组件有所区别,并且当前不会触发 <suspense>
。不过它们仍然可以包含异步组件作为后代,这样它们还是可以正常触发 <suspense>
。
← 插槽统一 过渡的 class 名更改 →