「这是我参与2022首次更文挑战的第39天,活动详情查看:2022首次更文挑战」。
我在写关于Vue3新特性系列的文章,今天的主要讲讲在Vue3中新特性中,非常有趣的Suspense组件。
什么是Suspense?
在React当中,Suspense 是一个特殊的组件,它在满足条件之前呈现指定内容而不是组件。这种情况通常是在您的组件功能中发生的异步操作,比如在用户等待时显示的一些特定的内容。在vue3中,终于也加入了类似的功能。
通常,在组件上渲染加载动画可以使用简单的 v-if 和 v-else 来实现,示例如下:
<div v-if="loading">
# loading animation
</div>
<div v-else>
...
</div>
使用 <suspense>,我们可以按照如下代码重写相同的功能。
<Suspense>
<template #default>
...
</template>
<template #fallback>
# loading animation
</template>
</Suspense>
注意,<suspense> 组件提供了两个插槽,#default 和#fallback。 #default 中的任何节点只有在其所有异步操作完成后才会呈现。否则,组件将呈现#fallback。
基本用法
下面的代码片段显示了一个简单的示例,说明在等待 API数据时使用<suspense> 呈现加载动画。
# User.vue
<template>
{{ data }}
</template>
<script setup>
import { ref } from 'vue'
import { fetchData } from './utils'
const data = ref(null)
data.value = await fetchData()
</script>
# Home.vue
<template>
<Suspense>
<template #default>
<User/>
</template>
<template #fallback>
Loading...
</template>
</Suspense>
</template>
<script setup>
import User from './User.vue'
</script>
在上面的例子中,Loading... 文本被渲染,直到 fetchData() 在 User.vue 中完成。需要注意的是,如果 <User/> 组件抛出任何错误,是缺少错误处理的。
在下面示例中,创建了一个 <SuspenseWithErrorHandling> 新组件来扩展 <suspense> 的使用并支持基本的错误处理。
# SuspenseWithErrorHandling.vue
<template>
<slot name="error" v-if="$slots?.error" />
<Suspense v-else>
<template #default>
<slot name="default" />
</template>
<template #fallback>
<slot name="fallback" />
</template>
</Suspense>
</template>
# Home.vue
<template>
<SuspenseWithErrorHandler>
<template #error v-if="error">
{{ error }}
</template>
<template #default>
<User/>
</template>
<template #fallback>
Loading...
</template>
</SuspenseWithErrorHandler>
</template>
<script setup>
import { ref, onErrorCaptured } from 'vue'
import User from './User.vue'
import SuspenseWithErrorHandling from './SuspenseWithErrorHandling.vue'
const error = ref(null)
onErrorCaptured(err => {
error.value = err
})
</script>
上述代码使用 onErrorCaptured 钩子来检测 <User/> 组件引发的错误。然后,使用新创建的 <SuspenseWithErrorHandler/> 显示此错误。这样,每当组件失败时,它就不会渲染#fallback,而是显示#error slot 中提供的元素。
总结
Suspense 是一个非常方便的组件,它能够以一种简单而优雅的方式显示备选内容,直到执行异步操作。使用 ErrorCaptured 生命周期钩子,还可以优雅地处理挂起组件中发生的错误。