返回介绍

五、suspense

发布于 2024-04-04 21:12:39 字数 3857 浏览 0 评论 0 收藏 0

API 可能随时会发生变动

在正确渲染组件之前进行一些异步请求是很常见的事。组件通常会在本地处理这种逻辑,绝大多数情况下这是非常完美的做法。

<suspense> 组件提供了另一个方案,允许将等待过程提升到组件树中处理,而不是在单个组件中

<template>
  <suspense>
  <!-- <suspense> 组件有两个插槽。它们都只接收一个直接子节点  -->
  <!-- default 插槽里的节点会尽可能展示出来。如果不能,则展示 fallback 插槽里的节点 -->
  <template #default>
    <todo-list />
  </template>
  <template #fallback>
    <div>
    Loading...
    </div>
  </template>
  </suspense>
</template>
<script>
export default {
  components: {
  TodoList: defineAsyncComponent(() => import('./TodoList.vue'))
  }
}
</script>

重要的是,异步组件不需要作为 <suspense> 的直接子节点。它可以出现在组件树任意深度的位置,且不需要出现在和 <suspense> 自身相同的模板中。只有所有的后代组件都准备就绪,该内容才会被认为解析完毕。

另一个触发 fallback 的方式是让后代组件从 setup 函数中返回一个 Promise。通常这是通过 async 实现的,而不是显式地返回一个 Promise:

export default {
  async setup() {
  // 在 `setup` 内部使用 `await` 需要非常小心
  // 因为大多数组合式 API 函数只会在
  // 第一个 `await` 之前工作
  const data = await loadData()

  // 它隐性地包裹在一个 Promise 内
  // 因为函数是 `async` 的
  return {
    // ...
  }
  }
}

子组件更新

一旦 <suspense>default 插槽里的内容被解析,则它只有在 default 根结点被替换的时候才能被再次触发。而树里的深层嵌套组件不足以让 <suspense> 回到等待状态。

如果根结点发生了变化,它会触发 pending 事件。然而,默认情况下,它不会更新 DOM 以展示 fallback 内容。取而代之的是,它会继续展示旧的 DOM,直到新组件准备就绪。这个行为可以通过 timeout prop 进行控制( defineAsyncComponent 组件的 timeout )。这个值是一个毫秒数,告诉 <suspense> 组件多久之后展示 fallback 。如果这个值是 0 则表示它在 <suspense> 进入等待状态时会立即显示。

事件

除了 pending 事件以外, <suspense> 组件还拥有 resolvefallback 事件。 resolve 事件会在 default 插槽完成新内容的解析之后被触发。 fallback 事件会在 fallback 插槽的内容展示的时候被触发。

这些事件可以用在诸如当新组件加载时在旧 DOM 上展示一个加载标识等场景

和其它组件结合

<suspense>](https://v3.cn.vuejs.org/api/built-in-components.html#transition) 和 [ 组件相结合是常见的情形。这些组件的嵌套顺序对于它们的正确工作很重要。

额外的,这些组件经常用于衔接 Vue Router<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>

Vue Router 有内置的基于动态导入的 组件懒加载 支持。它和异步组件有所区别,并且当前不会触发 <suspense> 。不过它们仍然可以包含异步组件作为后代,这样它们还是可以正常触发 <suspense>

onErrorCaptured 捕获 suspense 中出现的错误

<script>
	import { ref,onErrorCaptured } from 'vue';
  setup() {
  const captureError = ref(null);
    onErrorCaptured((e: any) => { // 捕获 suspense 中可能的错误
    captureError.value = e;
    return true; // 返回一个布尔值,表示是否继续向上传播
    })
  return {
    captureError
  }
  }
</script>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文