先看一下官网是怎么说的,下面是官网的介绍

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

<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>

<suspense> 组件有两个插槽。它们都只接收一个直接子节点。default插槽里的节点会尽可能展示出来。如果不能,则展示fallback插槽里的节点。

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

下面说说我自己的理解:<suspense>提供了两个插槽:default与fallback,两个插槽下只能有一个子节点,而异步组件没有必要直接放在default下,default下唯一的子节点下可以有很多个节点,而异步组件可以出现在这个子节点下的任意位置。且还可以作为在这个节点下的子组件的子组件出现

下面来验证一下我们的想法:

  1. 先写一个AsyncShow.vue异步组件,返回一个promise对象,不再是json。
<template>
  <h1>{{ result }}</h1>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  setup() {
    let promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        return resolve({ result: "每天都要元气满满" });
      }, 2000);
    });
    return promise;
  },
});
</script>
  1. 使用这个组件
<Suspense>
  <template #default>
     <AsyncShow></AsyncShow>
  </template>
  <template #fallback>
    <div>loading......</div>
  </template>
</Suspense>

alt

alt

两秒后文字变成了每天都要元气满满

  1. 在Suspense下新增一个子组件,并且把异步组件放在这个子组件中,代码就变成了如下这样
    <Suspense>
      <template #default>
        <Child></Child>
      </template>
      <template #fallback>
        <h1>loading......</h1>
      </template>
    </Suspense>
<template>
  <div class="child">
    <AsyncShow></AsyncShow>
  </div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import AsyncShow from "@/views/AsyncShow.vue";
export default defineComponent({
  components: {
    AsyncShow,
  },
});
</script>

刷新页面,两秒后文字变成了每天都要元气满满,说明我的理解正确^_^。

alt

alt