2024年前端最全「前端进阶」高性能渲染十万条数据(时间分片),面试yg

总结

技术学到手后,就要开始准备面试了,找工作的时候一定要好好准备简历,毕竟简历是找工作的敲门砖,还有就是要多做面试题,复习巩固。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

本文作为开篇,着重来介绍如何使用时间分片的方式来渲染大量数据,虚拟列表相关的内容,日后会持续整理。

最粗暴的做法(一次性渲染)


我们先来看看最粗暴的做法,一次性将大量数据插入到页面中:

    复制代码

    // 记录任务开始时间

    let now = Date.now();

    // 插入十万条数据

    const total = 100000;

    // 获取容器

    let ul = document.getElementById(‘container’);

    // 将数据插入容器中

    for (let i = 0; i < total; i++) {

    let li = document.createElement(‘li’);

    li.innerText = ~~(Math.random() * total)

    ul.appendChild(li);

    }

    console.log(‘JS运行时间:’,Date.now() - now);

    setTimeout(()=>{

    console.log(‘总运行时间:’,Date.now() - now);

    },0)

    // print: JS运行时间: 187

    // print: 总运行时间: 2844

    复制代码

    我们对十万条记录进行循环操作,JS的运行时间为187ms,还是蛮快的,但是最终渲染完成后的总时间确是2844ms

    简单说明一下,为何两次console.log的结果时间差异巨大,并且是如何简单来统计JS运行时间总渲染时间

    • 在 JS 的Event Loop中,当JS引擎所管理的执行栈中的事件以及所有微任务事件全部执行完后,才会触发渲染线程对页面进行渲染

    • 第一个console.log的触发时间是在页面进行渲染之前,此时得到的间隔时间为JS运行所需要的时间

    • 第二个console.log是放到 setTimeout 中的,它的触发时间是在渲染完成,在下一次Event Loop中执行的

    关于Event Loop的详细内容请参见这篇文章–>

    依照两次console.log的结果,可以得出结论:

    对于大量数据渲染的时候,JS运算并不是性能的瓶颈,性能的瓶颈主要在于渲染阶段

    使用定时器


    从上面的例子,我们已经知道,页面的卡顿是由于同时渲染大量DOM所引起的,所以我们考虑将渲染过程分批进行

    在这里,我们使用setTimeout来实现分批渲染

      复制代码

      //需要插入的容器

      let ul = document.getElementById(‘container’);

      // 插入十万条数据

      let total = 100000;

      // 一次插入 20 条

      let once = 20;

      //总页数

      let page = total/once

      //每条记录的索引

      let index = 0;

      //循环加载数据

      function loop(curTotal,curIndex){

      if(curTotal <= 0){

      return false;

      }

      //每页多少条

      let pageCount = Math.min(curTotal , once);

      setTimeout(()=>{

      for(let i = 0; i < pageCount; i++){

      let li = document.createElement(‘li’);

      li.innerText = curIndex + i + ’ : ’ + ~~(Math.random() * total)

      ul.appendChild(li)

      }

      loop(curTotal - pageCount,curIndex + pageCount)

      },0)

      }

      loop(total,index);

      复制代码

      用一个gif图来看一下效果

      我们可以看到,页面加载的时间已经非常快了,每次刷新时可以很快的看到第一屏的所有数据,但是当我们快速滚动页面的时候,会发现页面出现闪屏或白屏的现象

      为什么会出现闪屏现象呢

      首先,理清一些概念。FPS表示的是每秒钟画面更新次数。我们平时所看到的连续画面都是由一幅幅静止画面组成的,每幅画面称为一FPS是描述变化速度的物理量。

      大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次,FPS为60frame/s,为这个值的设定受屏幕分辨率、屏幕尺寸和显卡的影响。

      因此,当你对着电脑屏幕什么也不做的情况下,大多显示器也会以每秒60次的频率正在不断的更新屏幕上的图像。

      为什么你感觉不到这个变化?

      那是因为人的眼睛有视觉停留效应,即前一副画面留在大脑的印象还没消失,紧接着后一副画面就跟上来了, 这中间只间隔了16.7ms(1000/60≈16.7),所以会让你误以为屏幕上的图像是静止不动的。

      而屏幕给你的这种感觉是对的,试想一下,如果刷新频率变成1次/秒,屏幕上的图像就会出现严重的闪烁, 这样就很容易引起眼睛疲劳、酸痛和头晕目眩等症状。

      大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升。 因此,最平滑动画的最佳循环间隔是1000ms/60,约等于16.6ms。

      直观感受,不同帧率的体验:

      • 帧率能够达到 50 ~ 60 FPS 的动画将会相当流畅,让人倍感舒适;

      • 帧率在 30 ~ 50 FPS 之间的动画,因各人敏感程度不同,舒适度因人而异;

      • 帧率在 30 FPS 以下的动画,让人感觉到明显的卡顿和不适感;

      • 帧率波动很大的动画,亦会使人感觉到卡顿。

      简单聊一下 setTimeout 和闪屏现象

      • setTimeout的执行时间并不是确定的。在JS中,setTimeout任务被放进事件队列中,只有主线程执行完才会去检查事件队列中的任务是否需要执行,因此setTimeout的实际执行时间可能会比其设定的时间晚一些。

      • 刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的刷新频率可能会不同,而setTimeout只能设置一个固定时间间隔,这个时间不一定和屏幕的刷新时间相同。

      以上两种情况都会导致setTimeout的执行步调和屏幕的刷新步调不一致。

      setTimeout中对dom进行操作,必须要等到屏幕下次绘制时才能更新到屏幕上,如果两者步调不一致,就可能导致中间某一帧的操作被跨越过去,而直接更新下一帧的元素,从而导致丢帧现象。

      使用 requestAnimationFrame


      setTimeout相比,requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机。

      如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象。

      我们使用requestAnimationFrame来进行分批渲染:

        复制代码

        //需要插入的容器

        let ul = document.getElementById(‘container’);

        // 插入十万条数据

        let total = 100000;

        总结

        技术学到手后,就要开始准备面试了,找工作的时候一定要好好准备简历,毕竟简历是找工作的敲门砖,还有就是要多做面试题,复习巩固。

        开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

        = document.getElementById(‘container’);

        // 插入十万条数据

        let total = 100000;

        总结

        技术学到手后,就要开始准备面试了,找工作的时候一定要好好准备简历,毕竟简历是找工作的敲门砖,还有就是要多做面试题,复习巩固。

        开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

        [外链图片转存中…(img-C2ivoWgt-1715517125835)]

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

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

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

        请填写红包祝福语或标题

        红包个数最小为10个

        红包金额最低5元

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

        抵扣说明:

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

        余额充值