Vue3 这种方式优化白屏时间超级好用,我不允许你还不知道!

前端优化是一个永恒的话题,每个前端开发者都希望自己的页面能够快速加载,给用户良好的体验。

但是在实际开发中,我们经常会遇到一个棘手的问题,那就是首页白屏问题。

首页白屏问题是指用户打开页面后,需要等待很长时间才能看到页面内容,这会让用户感到不耐烦,甚至流失。

造成白屏的原因有很多,比如网络延迟、JS 加载过多、渲染性能不佳等等。

针对不同的原因,我们需要采取不同的优化策略。

今天子辰就和大家讨论一种常见的场景,以及其中的一种优化手段。

这种优化手段可能很多人都不知道,但是它非常有效,可以大幅度提升用户的感知效率。

场景

我们先来看一下代码:

<template>
  <div class="container">
    <div v-for="n in 100">
      <heavy-comp></heavy-comp>
    </div>
  </div>
</template>

<script setup>
  import HeavyComp from './components/HeavyComp.vue';
</script>

这里我们导入了一个叫做 HeavyComp 的组件,这个组件里有很多很多的元素,特别是在大屏项目里元素可能特别密集。

然后我们将这个组件循环了 100 次,每一次循环渲染一次。

我们来看一下它的运行效果。

我们会发现有长时间的等待,最后一起把这些组件渲染出来。

然后我们使用浏览器的调试工具做一下性能分析。

可以看出 2686 毫秒在加载 JS,2795 毫秒在渲染。

这样的页面对于用户而言是无法接受的,那么怎么来优化呢?

优化

其实主要的思路就是让这些组件一部分一部分的渲染,一起渲染压力太大要分摊一下,先渲染其中一部分,让用户能够看到,然后再持续的渲染剩下的部分。

虽然总的时间没有变化,甚至还有可能会增加,但是对于用户的感知而言,从用户打开页面到看到东西这段时间被大幅度的缩减了。

这里我们先直接使用写好的优化方法。

<template>
  <div class="container">
    <div v-for="n in 100">
      <!-- 在渲染组件的时候,我们可以利用 defer 函数来进行 if 判断 -->
      <heavy-comp v-if="defer(n)"></heavy-comp>
    </div>
  </div>
</template>

<script setup>
import HeavyComp from './components/HeavyComp.vue';
// 导入一个我已经写好的函数
import { useDefer } from './useDefer';
// 这个函数返回一个方法
const defer = useDefer();
</script>

那么这个 defer 函数有什么作用呢?

渲染帧同学们肯定都学过,就是在一个渲染时间线内,它是分成很多小段,每一段都是一个渲染帧,每一个渲染帧的间隔是 16.6 毫秒。

假如说第一个渲染帧叫第一次渲染,第二个渲染帧叫第二次渲染,依次类推。

那么这个 defer(n) 表达的意思就是,目前渲染帧有没有超过这个 n。

举个例子:比如说 defer(10),传入 10,表达的意思是当渲染的帧数是第一帧的时候,返回 false,第二帧的时候还是返回 false,只有当渲染帧大于等于第十帧的时候才返回 true,就这么简单。

当它返回 false 的时候,由于我们使用了 v-if,那么这个组件它就不会渲染。

换句话说,这里给它传一个 n,就表示它循环了 100 次,第一个组件的时候 n 是 1,就表示第一帧的时候渲染第一个组件,第二个组件的时候 n 是 2,就表示第二帧的时候渲染第二个组件,依次类推。

我们这样子做了以后再来看一下页面的渲染。

我们发现很快就得到了响应,尽管总时间没有变化,因为它还在持续渲染,但是用户感知到它的效率已经大大提升了,我们再次用性能分析工具分析一下。

可以看到,渲染过程被分成了一帧一帧进行渲染,避免了页面长时间的卡顿,每一次渲染用户都能看到它的渲染结果。

这有点像 React 的 fiber 架构,在 Vue3 中也有类似的概念。

其实都是利用浏览器空闲时间来进行任务调度和拆分。

接下来我们来看看这个函数到底是怎么实现的。

useDefer 函数

import { ref } from "vue";
// 函数接收一个参数,表示监测的最大帧数,这里默认值是 1000
// 如果说你渲染的东西特别多可以传入一个值
export function useDefer(maxFrameCount = 1000) {
  // 然后开始计数
  const frameCount = ref(0);
  const refreshFrameCount = () => {
    requestAnimationFrame(() => {
      // 每一次 requestAnimationFrame 就计数加一
      // 表示当前渲染的帧数变多了一帧
      frameCount.value++;
      // 只要当前帧数小于最大帧数就递归执行
      if (frameCount.value < maxFrameCount) {
        refreshFrameCount();
      }
    });
  };
  refreshFrameCount();
  // 返回一个函数,接收传递进来的 n
  return function (showInFrameCount) {
    // 判断当前渲染的帧数有没有大于 n
    return frameCount.value >= showInFrameCount;
  };
}

这就是经典的使用 defer 来优化白屏问题和提升用户感知效率的一个例子。

通过使用 requestAnimationFrame 和 v-if 来控制组件何时进行渲染。

让页面内容逐步展现出来,而不是等待所有内容都加载完毕再显示出来,从而提高用户体验和满意度。

总结

前端优化之白屏问题是一个非常重要而又常见的问题,我们需要根据不同场景采取不同策略。

本文介绍了其中一种场景和优化方法,即利用 defer 函数来控制组件何时进行渲染,让页面内容逐步展现出来。从而提高用户感知效率和体验。

当然还有其他优化方法和技巧。

比如使用骨架屏、预加载、懒加载、代码分割等等。

前端优化是一个永无止境而又充满乐趣和挑战性的领域,希望本文能给你提供一些启发和参考。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值