Vue3.2 内置组件 Suspense

Suspense 组件

Suspense是Vue3.2新增的内置组件,与React.Suspense组件类似。
Suspense有两个插槽:defaultfallback
default插槽中存放具有深层异步依赖的组件/(异步组件)
default中的组件状态未变成fulfilled(完成且未抛出异常)时,会显示fallback插槽中的内容

1.配合defineAsyncComponent懒加载组件

child component A

<!-- ./components/A.vue -->
<template>
  <h1>hello</h1>
</template>

parent component

<script setup lang="ts">
import {defineAsyncComponent} from "vue";
const A = defineAsyncComponent(() => import('./components/A.vue'))
</script>

<template>
  <Suspense>
    <A/>
    <template #fallback>
      <p>loading...</p>
    </template>
  </Suspense>
</template>

2.使用async setup

child component B

<!-- ./components/B.vue -->
<script lang="ts" setup>
const getTitle = () => {
  return new Promise<string>((resolve, reject) => {
    setTimeout(() => {
      resolve('hello')
      // reject(new Error('wo wo wo ~'))
    }, 3000)
  })
}
// 直接在script setup 使用顶层await, vue 会使得 setup函数变成 async setup() {}
const title = await getTitle()
</script>
<template>
  <h1>{{title}}</h1>
</template>

parent component

<script setup lang="ts">
import B from './components/B.vue'
</script>

<template>
  <Suspense>
    <B/>
    <template #fallback>
      <p>loading...</p>
    </template>
  </Suspense>
</template>

3.配合vueRouter使用

<RouterView v-slot="{ Component }">
  <template v-if="Component">
    <Transition mode="out-in">
      <KeepAlive>
        <Suspense>
          <!-- 主要内容 -->
          <component :is="Component"></component>

          <!-- 加载中状态 -->
          <template #fallback>
            正在加载...
          </template>
        </Suspense>
      </KeepAlive>
    </Transition>
  </template>
</RouterView>

4.错误边界

<Suspense> 组件自身目前还不提供错误处理,不过可以使用 errorCaptured 选项或者 onErrorCaptured() 钩子,在使用到 <Suspense> 的父组件中捕获和处理异步错误。

以 component B 为例 将getTitleresolve 改为 reject

- resolve('hello')
+ reject(new Error('wo wo wo ~'))

parent component


<script setup lang="ts">
import {defineAsyncComponent, onErrorCaptured, ref} from "vue";

const B = defineAsyncComponent(() => import('./components/B.vue'))

const errorMessage = ref<string | null>(null)

onErrorCaptured((e) => {
  errorMessage.value = e instanceof Error ? e.message : (e || 'has error')
})
</script>

<template>
  <Suspense>
    <B/>
    <template #fallback>
      <p>{{ errorMessage || 'loading...' }}</p>
    </template>
  </Suspense>
</template>
posted @ 2022-06-16 12:17  demo_you  阅读(550)  评论(0编辑  收藏  举报