一般有两种做法
1.时间分片
setTimeout是宏任务,先执行完所有的微任务,才会触发渲染线程对页面进行渲染,
而setTimeout的触发时间是渲染完成,在下一次eventloop中执行的。
根据以上两次log,js运算并不是性能的瓶颈,瓶颈主要在渲染阶段。
怎么办呢?
使用定时器,在这里,我们使用setTimeout
来实现分批渲染
前置知识:
FPS
表示的是每秒钟画面更新次数。我们平时所看到的连续画面都是由一幅幅静止画面组成的,每幅画面称为一帧
,FPS
是描述帧
变化速度的物理量。
大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次,FPS
为60frame/s,为这个值的设定受屏幕分辨率、屏幕尺寸和显卡的影响。
- 帧率能够达到 50 ~ 60 FPS 的动画将会相当流畅,让人倍感舒适;
- 帧率在 30 ~ 50 FPS 之间的动画,因各人敏感程度不同,舒适度因人而异;
- 帧率在 30 FPS 以下的动画,让人感觉到明显的卡顿和不适感;
- 帧率波动很大的动画,亦会使人感觉到卡顿。
setTimeout
的执行时间并不是确定的。在JS中,setTimeout
任务被放进事件队列中,只有主线程执行完才会去检查事件队列中的任务是否需要执行,因此setTimeout
的实际执行时间可能会比其设定的时间晚一些。刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的刷新频率可能会不同,而setTimeout
只能设置一个固定时间间隔,这个时间不一定和屏幕的刷新时间相同。以上两种情况都会导致setTimeout的执行步调和屏幕的刷新步调不一致。
在setTimeout
中对dom进行操作,必须要等到屏幕下次绘制时才能更新到屏幕上,如果两者步调不一致,就可能导致中间某一帧的操作被跨越过去,而直接更新下一帧的元素,从而导致丢帧现象。
因此使用requestAnimationFrame
与setTimeout
相比,requestAnimationFrame
最大的优势是由系统来决定回调函数的执行时机。
//需要插入的容器 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); window.requestAnimationFrame(function(){ 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) }) } loop(total,index);
再优化的话,使用DocumentFragment
DocumentFragment,文档片段接口,表示一个没有父级文件的最小文档对象。它被作为一个轻量版的Document使用,用于存储已排好版的或尚未打理好格式的XML片段。最大的区别是因为DocumentFragment不是真实DOM树的一部分,它的变化不会触发DOM树的(重新渲染) ,且不会导致性能等问题。 可以使用document.createDocumentFragment方法或者构造函数来创建一个空的DocumentFragment
2.虚拟列表
虚拟列表
其实是按需显示的一种实现,即只对可见区域
进行渲染,对非可见区域
中的数据不渲染或部分渲染的技术,从而达到极高的渲染性能。
实现
虚拟列表的实现,实际上就是在首屏加载的时候,只加载可视区域
内需要的列表项,当滚动发生时,动态通过计算获得可视区域
内的列表项,并将非可视区域
内存在的列表项删除。
- 计算当前
可视区域
起始数据索引(startIndex
) - 计算当前
可视区域
结束数据索引(endIndex
) - 计算当前
可视区域的
数据,并渲染到页面中 - 计算
startIndex
对应的数据在整个列表中的偏移位置startOffset
并设置到列表上
有图片怎么办?
那就使用ResizeObserver
标签:流畅,渲染,海量,列表,let,FPS,屏幕,setTimeout,页面 From: https://www.cnblogs.com/alwaysrun/p/17179095.html