1.现假设有如下需求,渲染10W条数据到页面中,显示内容为1-100000,那还不简单,直接开始写.
let count = 100000;
const ul = document.getElementById("ul")function insert() {
for (let i = 0;
i < count;
i++) {
let oli = document.createElement("li");
oli.innerText = curIndex + i;
ul.appendChild(oli);
}
}
非常简单,但是试想是10W条数据的请求,那么页面性能方面肯定不足的,耗时如下:
文章图片
2.现将其分片加载,每次请求2000条数据,性能有所优化
let count = 100000;
const ul = document.getElementById("ul")
const once = 2000;
function insert(curTotal, curIndex) {
if (curTotal <= 0) return;
setTimeout(function(){
for (let i = 0;
i < once;
i++) {
let oli = document.createElement("li");
oli.innerText = curIndex + i;
ul.appendChild(oli);
}
},0)insert(curTotal - once, curIndex + once);
}
insert(count, 0);
文章图片
3.对
event loop
有了解的都知道setTimeout并不是多少S之后执行,而是多少S之后将其放入event queue
事件队列,考虑这方面的因素,可以利用requestAnimationFrame
对其进行优化,requestAnimationFrame
会在下次重绘前执行回调函数.function insert(curTotal, curIndex) {
if (curTotal <= 0) return;
window.requestAnimationFrame(function(){
for (let i = 0;
i < once;
i++) {
let oli = document.createElement("li");
oli.innerText = curIndex + i;
ul.appendChild(oli);
}
},0)insert(curTotal - once, curIndex + once);
}
insert(count, 0);
文章图片
可以看到时间并没有减少,反而增加了.可能setTimeout每次都被及时的从队列中取了出来,或者缓存等因素的影响造成一些差异,但是使用
requestAnimationFrame
总是好的4.经过上述优化,已经比较好的,但是忽略了一个重要的问题,页面渲染中的回流、重绘,页面中每次添加一个li都会进行一次回流操作,回流操作是非常消耗性能的,需要减少其的使用,解决方案是可以多个回流一起操作,可以使用文档碎片(documentFragment)这个概念
let count = 100000;
const ul = document.getElementById("ul")
const once = 2000;
function insert(curTotal, curIndex) {
if (curTotal <= 0) return;
window.requestAnimationFrame(() => {
let frame=document.createDocumentFragment();
for (let i = 0;
i < once;
i++) {
let oli = document.createElement("li");
oli.innerText = curIndex + i;
frame.appendChild(oli);
}
ul.appendChild(frame);
})insert(curTotal - once, curIndex + once);
}
insert(count, 0);
【万条数据渲染的优化方案】
文章图片