关于Vue3的新特性Suspense的实验性测试

海星吧 2022-7-20 5015

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才行。

以上是我对这个组件的实验性测试,如果你有什么好的发现或其他想要交流的话,敬请留言。
 
(σ゚∀゚)σ..:*☆ 这里是海星吧,我们下次见,拜拜。
弱鸡程序员年底还在加班
最新回复 (18)
  • 某块面包 2022-7-20
    1 2
    焯,看不懂
    我想玩手机……
  • 星辰乄 2022-7-20
    0 3
    可惜我不是数据算法分析专业的学生,只能做到看懂但做不到分析。

    loading的过程只在第一次使用页面时加载,是不是说在组件以及其属性完全相同的情况下只在第一次加载时使用呢?
    这个感觉和cookie或者是session很像呢,就比如session内部存在的一个生命周期,在生命周期内,其数据会序列化。那由此猜测这个loading的过程会不会在内部的算法中,认为加载组件的时间是有一个阈值的,如果超过这个值就可以显示这个loading,如果低于这个threshold,内部就会认定,所使用时间没有必要显示loading呢?

    这可能是和前端的驻留性有关?网页只在第一次加载时对持久化数据进行一次大面积编译解释,在后续使用时,如果遇到持久化数据且没有更改记录,就会尽可能偷懒(我以前好像看到过这本书,关于计算机的懒惰性,或者说是滞后性。),使用驻留的数据,。因为使用这个数据是不需要通过编译解释阶段直接拿过来用,所以会非常的快。还有对待热点代码,我不知道前端是不是也有类似于热点探测功能的算法,或许在前端方面,认为对组件或者组件组的处理是硬性的热点代码,所以无论整体是否进行一次大面积编译解释,对组件或者类似的组件组的代码会进行热点探测。
    前端讲究效率,我感觉很有可能。
    纯属个人猜测,对前端属实不太了解,只能凭空猜测了。

    ★ 携飞仙以遨游,抱明月而长终。
  • 冷泉法克斯 2022-7-20
    0 4
    undefined
    信仰是为了虚幻之人
  • 喀秋莎 2022-7-20
    0 5
    在?做个本子下载插件?
    我在上班,别发骚图了。
  • 涙がtears 2022-7-20
    0 6
    undefined
    北纬三十度的黑
  • 海星吧 2022-7-20
    0 7
    星辰乄 可惜我不是数据算法分析专业的学生,只能做到看懂但做不到分析。 loading的过程只在第一次使用页面时加载,是不是说在组件以及其属性完全相同的情况下只在第一次加载时使用呢? 这个感觉和cook ...
    loading的状态不仅仅只在页面进入时加载,在任何有需要的时候,loading都是可以发生效用的。
    描述一个场景,如果一个管理后台拥有切换布局的功能,那么这个切换的时候会造成大量的render,
    这种比较耗时且可能切换频繁的时候,可以将 Suspense 中的 fallback 作为一个雪碧图 遮挡 页面。
    还有 Suspense 是包裹异步组件的,也就是说不用在 onMounted  hook 中再去调用接口,而是直接在
    script setup 语法糖中调用接口请求数据,然后 让Suspense 进入fallback也是可以的。
    因为被 setup 属性描述的script本身就可以作为一个async 函数使用。
    弱鸡程序员年底还在加班
  • 欧派兽 2022-7-20
    0 8
    奖励三级精华
    1:管理员给你移区后会显示移到了你之前发帖的区。 2:点击我作为楼主发帖时一楼下的图片签名,可以跳转到站规教程贴。 3:多次水贴水回复会封号哦? 4:不知道回什么的时候就点“里世界专属”,一键随机生成几种回复内容。 5:祝你在里世界玩得愉快!
  • 星辰乄 2022-7-20
    0 9
    海星吧 loading的状态不仅仅只在页面进入时加载,在任何有需要的时候,loading都是可以发生效用的。 描述一个场景,如果一个管理后台拥有切换布局的功能,那么这个切换的时候会造成大量的render, ...
    针对你说的场景,存在两种情况,
    第一种,客户端完全的第一次进行服务端请求,或者说客户端的该次请求是在对服务端的请求周期之外,此时本地资源已经释放,这种情况会产生大量render,客户端资源会得到第一次的loading,我认为这是其默认出现的可能,也就是雪碧图。

    第二种情况,客户端虽然是第一次进行服务端请求,但其资源配置是在请求周期之内,本地资源尚未释放,这时其正常的思路应该是优先调用本地未释放的资源,这样不仅可以提高界面应用效率,也能提高子网段整体async,因为这样做,可以使得范围内主机,由多段async转换成单段sync,此时调用本地资源的时间往往要比请求服务端快很多,或许loading这个机制内部的核心会判定这种情况的时间可以忽略不记,所以不会显示loading。
    我观察到你的文档更新中的描述,虽没有完全指明,但符合预加载模式的猜想,通过该模式得到所有的组件-事件,在切换组件时,将整个动态的切换模式转换成了静态切换。

    这句话可能比较难理解,我的解释是,原本在客户端,对于一个多元素的组件组应该存在一个独立事件线程监视,若组件组元素发生变化,线程事件触发,请求至服务端,这是动态的,实时的。
    我猜测,文中提到的机制将这种动态的触发转换成了一种提前量,也就是事件触发之前就将该事件进行"模拟触发",保存触发结果,在后续操作中真正触发时直接调用该资源,而不必等待事件被触发时。

    这也是我想说的,loading应当只在第一次使用界面时产生效果,当然我所说的都是指的静态page资源,但即便是ajax动态资源也应当有着类似的缓存机制,但机制不唯一,毕竟对动态的要求通常会严格很多。

    这种操作可能是基于缓存机制,虽然我没有实际的研究过。
    要证明的话可以试一试用动态ajax加载,在加载过程中显示loading,如果不加timeout时,只在加载第一组数据时显示loading,那或许这么猜测是对的;如果每次加载数据都会显示loading,那就需要另作分析了。
    ★ 携飞仙以遨游,抱明月而长终。
  • 糸色望已绝望 2022-7-20
    1 10
    奇怪的知识……没有增加
    不是萝莉控,只是女朋友刚好是萝莉罢了
  • 无头骑士 2022-7-20
    0 11
    麻瓜了
    你讲话好冷漠,好像我不曾让你快乐过
  • 喜漫如性 2022-7-20
    0 12
    我看过一位学长也做过系统。。。虽说也和我讲过,教过我。。但似乎并没啥用(依旧看不懂(...
    愿衣襟带花,愿岁月风平
  • KoXue 2022-7-20
    0 13
    厚礼些,看不懂
    “嘘,长夜漫漫,处处险恶。”
  • 海星吧 2022-7-21
    0 14
    星辰乄 针对你说的场景,存在两种情况, 第一种,客户端完全的第一次进行服务端请求,或者说客户端的该次请求是在对服务端的请求周期之外,此时本地资源已经释放,这种情况会产生大量render,客户端资源会得到第一 ...
    遇上同行了。
    反正这东西就是拿来参考的,具体情况具体分析,该用到业务中的时候也会有莫名其妙的需求。
    比如老板让你加长loading时间然后告诉甲方要优化得加钱。
    弱鸡程序员年底还在加班
  • 海星吧 2022-7-21
    0 15
    欧派兽 奖励三级精华
    感谢。
    弱鸡程序员年底还在加班
  • 海星吧 2022-7-21
    1 16
    星辰乄 针对你说的场景,存在两种情况, 第一种,客户端完全的第一次进行服务端请求,或者说客户端的该次请求是在对服务端的请求周期之外,此时本地资源已经释放,这种情况会产生大量render,客户端资源会得到第一 ...

    还有这个场景可不是用的复数组件哦,这个是用vue的component内置组件,用is属性来判断需要使用的是那个组件,我目前写了个后台的项目就是用的component来切换布局的。

    目前只做了这两种布局,后面还得加主题,搞完这套我就丢git上。

    弱鸡程序员年底还在加班
  • 奈何桥头逗鬼 2022-7-23
    0 17
    看来我学编程的道路还很长啊~
    交嘉隶人,饮水堵源
  • 海星吧 2022-7-23
    0 18

    https://acgn.zone/thread-14203.htm

    分享这个项目git的文章

    弱鸡程序员年底还在加班
  • 海星吧 2022-7-23
    0 19
    奈何桥头逗鬼 看来我学编程的道路还很长啊~
    没啥难的,前端用vue的多看文档就行了。
    弱鸡程序员年底还在加班
    • ACG里世界
      20
          
返回
发新帖