使用defer算法优化白屏时间
发表于:2024-03-05 |

前言

昨天晚上刷小视频的时候刷到了这个东西,发现挺有意思的,就和大家分享一下这个东西。

为啥会有白屏

我们都知道,现在的网页基本都是SPA单页面应用,也就是说,我们的网页是一次性将所有的资源都加载完毕,然后再进行渲染。这样的话,就会出现一个问题,就是白屏时间过长。因为我们的资源都是一次性加载完毕的,所以我们的白屏时间就会很长。有时候是因为js导致我们的白屏时间过长,今天讲的这个是因为dom导致的白屏时间过长。

白屏效果展示

我写了很简单的一个循环dom代码

1
2
3
4
5
6
7
<template>
<div v-for="n in 300">
<t-row>
<t-card :title="`标题${n}`" v-for="j in 100"></t-card>
</t-row>
</div>
</template>

我们先来看一下白屏效果,我们先来看一下没有使用defer算法的代码和造成的白屏效果。

添加defer算法

我们在不同的帧率显示不同的dom,帧率越后面的dom越晚显示,这样就可以减少白屏时间了。

hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { onUnmounted, ref, getCurrentInstance } from 'vue';

export function useDefer(maxCount = 100) {
const frameCount = ref(0); //定义一个计数器变量,用于控制 defer 动画的次数,当为 0
const instance = getCurrentInstance(); //获取当前实例对象,可以是 vm 对象或自定义实例。这个对象包含了一些方法,用于控制动画。 (请参见该实例的方法) 创建 defer 动画时,将 frameCount.value 加 1 并将其写入到动画定时器中,每当该变量的值大于等于 1 时,将重新开始定时器,以便在定时器中计数。
let rafId;
function updateFrameCount() {
rafId = requestAnimationFrame(() => {
//requestAnimationFrame来设置当前已经渲染到哪一帧了
frameCount.value++;
if (frameCount.value >= maxCount) {
cancelAnimationFrame(rafId);
return;
}
updateFrameCount();
});
}
updateFrameCount();

onUnmounted(() => {
cancelAnimationFrame(rafId);
}, instance);

return function defer(n) {
return frameCount.value >= n;
};
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<div v-for="n in 300">
<t-row v-if="defer(n)">
<t-card :title="`标题${n}`" v-for="j in 100"></t-card>
</t-row>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
import {useDefer} from '@/hooks/useDefer';
const defer=useDefer(300);
</script>

代码讲解

frameCount首先必须要定义为ref,目的就是为了实时渲染,实现dom的双向绑定。我们通过请求动画帧的方式(咱们学3D的对这个可熟悉了)。然后页面即将挂载完成的时候请求动画帧的方法就给关了,超过最大帧数目的时候,也把请求动画帧关了,所以你要确保在使用的时候,你的页面已经挂载完成了,不然就会出现问题。

优化效果

因为太快了,我就从其他页面跳过来给大家看看效果,我么可以看到一下子就出来了,但是仔细看右边的滚动条可以看到它是慢慢在加载元素的

结语

本篇文章就到这里了,更多内容敬请期待,债见~

上一篇:
【算法学习】01-时间复杂度
下一篇:
【JAVA学习】04-跟着黑马程序员课程敲全栈项目(一)