前端页面渲染多条数据的性能优化
创始人
2025-05-31 23:03:26

后端一次性返回了10w条数据,前端该如何处理?
这个问题其实是考察面试者对性能优化的理解。我们早点,对于大量数据渲染的时候,JS运算并不是性能的瓶颈,性能的瓶颈主要在于渲染阶段,所以页面的卡顿是由于同时渲染大量DOM所引起的。

前端长数据渲染方案:

一、一次性渲染



Document

    二、使用定时器进行分页渲染

    
    Document

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

      刷新频率受屏幕分辨率和屏幕尺寸的影响,大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次,因此不同设备的刷新频率可能会不同,而 setTimeout只能设置一个固定时间间隔,这个时间不一定和屏幕的刷新时间相同。

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

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

      三、使用 requestAnimationFrame

      使用 requestAnimationFrame 代替 setTimeout,减少了重排的次数, requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机,极大提高了性能

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

      const renderList = async (page) => {if (page >= totalPage) return;//使用 requestAnimationFrame 代替 setTimeout,减少重排次数requestAnimationFrame(() => {for (let i = page * limit; i < page * limit + limit; i++) {const li = document.createElement("li");li.innerHTML = `${i}---${~~(Math.random() * total)}`;ul.appendChild(li);}renderList(page + 1);});};renderList(page);
      

      四、使用 DocumentFragment

      先解释一下什么是 DocumentFragment

      1. DocumentFragments 是DOM节点。它们不是主DOM树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树。
      2. 在DOM树中,文档片段被其所有的子元素所代替。因为文档片段存在于内存中,并不在DOM树中。
      3. 所以将子元素插入到文档片段时不会引起【页面回流】(对元素位置和几何上的计算)。

      因此,使用文档片段通常会带来更好的性能。

      const renderList = async (page) => {if (page >= totalPage) return;requestAnimationFrame(() => {let fragment =  document.createDocumentFragment();for (let i = page * limit; i < page * limit + limit; i++) {const li = document.createElement("li");li.innerHTML = `${i}---${~~(Math.random() * total)}`;fragment.appendChild(li)}ul.appendChild(fragment)renderList(page + 1);});};renderList(page);
      

      五、懒渲染/延迟渲染scrollTop、getBoundingClientRect

      要获取用户的滚动位置,我们可以在列表末尾添加一个空节点空白。每当视口出现空白时,就意味着用户已经滚动到网页底部,这意味着我们需要继续渲染数据。

      同时,我们可以使用getBoundingClientRect来判断空白是否在页面底部。

      使用 Vue 的示例代码:

      
      

      相关内容

      热门资讯

      今年我省粮食产量达515.56... (来源:辽宁日报)转自:辽宁日报 图为在中储粮(盘锦)储运有限公司,装运粮食的重型卡车排起长队...
      国家发展改革委部署促进投资止跌... (来源:辽宁日报)转自:辽宁日报 新华社北京12月13日电 (记者魏玉坤) 记者13日从全国发展和改...
      江苏省实施《中华人民共和国森林... (来源:新华日报) 目 录 第一章 总则 第二章 森林、林木和林地权属管理...
      姜堰数字化产品讲“活”理论 (来源:新华日报) □ 本报记者 卢佳乐 通讯员 姜宣 “王教授,您约我‘喝茶论道’,...
      联合国维和部队在苏丹遇袭 6人... 转自:财联社【联合国维和部队在苏丹遇袭 6人死亡】财联社12月14日电,当地时间13日,苏丹武装部队...