Suspense 是vue3中将异步组件提升到组件树中的异步组件包容器。
这个组件效果和vue3的异步组件API defineAsyncComponent 相似
其目的都是在组件做异步请求的时候,显示一个loading的等待。
为此我做了一个关于 Suspense 的实验。
我这个项目使用了 tailwind.css 作为减少我样式编写的库,安利一下。
首先准备好两个组件

textBlue.vue
<template>
	<div class="text-blue-400">文字1</div>
</template>
<script setup>
const sleep = (delay = 2000) =>
	new Promise((resp) => setTimeout(() => resp(), delay));
await sleep(2000);
</script>
textGreen.vue
<template>
    <div class="text-green-400">
        文字2
    </div>
</template>
<script setup>
const sleep = (delay = 2000) =>
	new Promise((resp) => setTimeout(() => resp(), delay));
await sleep(2000);
</script>
 
这两个组件中我使用了sleep函数作为异步请求的模拟
 
以下是我实验的index组件。
<template>
	<div class="card">
		<p>测试切换组件</p>
		<p>{{ componentType }}</p>
		<el-radio-group v-model="componentType">
			<el-radio
				v-for="item in types"
				:label="item.label"
				:key="item.label"
			></el-radio>
		</el-radio-group>
		<p>Suspense : </p>
		<transition mode="out-in" name="el-fade-in-linear">
			<Suspense
				@pending="pendingEnv"
				@resolve="resolveEnv"
				@fallback="fallbackEnv"
				:timeout="0"
			>
				<template #default >
					<component :is="componentIs" :key="componentIsKey"></component>
				</template>
				<template #fallback>
					<loadingCmd></loadingCmd>
				</template>
			</Suspense>
		</transition>
	</div>
</template>
<script setup>
import textBlue from "./textBlue";
import textGreen from "./textGreen";
import loadingCmd from "./loading";
import errorCmd from "./error";
import { ref, defineAsyncComponent, computed } from "vue-demi";
const componentType = ref("textBlue");
const componentIs = computed(
	() =>
		types.find((a) => a.label == componentType.value).component || errorCmd
);
const componentIsKey = computed(() => componentType.value || "error");
const types = [
	{
		label: "textBlue",
		component: textBlue,
	},
	{
		label: "textGreen",
		component: textGreen,
	},
];
function pendingEnv() {
	console.log("发生变化");
}
function resolveEnv() {
	console.log("加载完成");
}
function fallbackEnv() {
	console.log("加载 loading");
}
</script>

这是页面的效果。
刚开始看是没啥,但是我组件切换的时候需要异步请求数据,这个时候不希望用户看到没有数据的组件,
给用户一个等待响应的等待页面。
Suspense组件目前有两个插槽,三个事件,一个属性
插槽
一个是 #default
一个是 #fallback
事件
@pending 组件发生变化时
@fallback  组件发生变化后进入fallback插槽
@resolve   组件加载完成后结束fallback插槽的显示进入到业务组件中
 
default是你放正常的组件时的插槽,fallback是loading状态组件的插槽,
这里有一个很尬的地方,如果不在 Suspense 中使用 timeout这个属性,那么这个loading就只会有一次被显示,
我之前测试了它的事件,结果发现除了第一次进入页面的时候,它会加载loading组件,
在我切换组件的时候,它反而只会触发pending 和 resolve  ,fallback  事件并不会触发,并且#fallback  插槽也不会进入。
在我翻阅文档后才发现这点,当时没有仔细看,后面才发现这个感觉好坑啊。。
 
 
给你们看看没有加timeout的时候是什么样子


这是进入页面时发生的变化,但是我切换组件的时候
可以看到并没有触发fallback函数,也没有像第一次进入的时候加载loading
那再来看看加上timeout = ‘0’是什么样子
可以看到组件被切换的时候,Suspense触发了fallback并进入了loading插槽。
所以这个组件如果需要反复的加载loading的话,还是得使用timeout属性赋值为0才行。
以上是我对这个组件的实验性测试,如果你有什么好的发现或其他想要交流的话,敬请留言。
 
(σ゚∀゚)σ..:*☆ 这里是海星吧,我们下次见,拜拜。