如何渲染几万条数据不卡住页面?也就是说不能一次性将几万条数据都渲染出来,而是应该一次渲染一部分DOM,那么可以通过requestAnimationFrame
来每 16 ms 刷新一次。
window.requestAnimationFrame()
告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
- 语法
1
| window.requestAnimationFrame(callback);
|
- 参数 callback是requestAnimationFrame的回调函数。该回调函数会被传入DOMHighResTimeStamp参数,该参数与performance.now()的返回值相同。浏览器下一次刷新时就会执行这个回调函数。
- 返回值 ID是requestAnimationFrame的调用时的返回值,是其在回调列表中的唯一的标识。你可以传这个值给
window.cancelAnimationFrame(ID)
以取消本次回调函数。
下面我们就可以通过代码自己模拟一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <ul>控件</ul> <script> setTimeout(() => { // 插入十万条数据 const total = 100000 // 一次插入 20 条,如果觉得性能不好就减少 const once = 20 // 渲染数据总共需要几次 const loopCount = total / once let countOfRender = 0 let ul = document.querySelector("ul"); function add() { // 优化性能,插入不会造成回流 const fragment = document.createDocumentFragment(); for (let i = 0; i < once; i++) { const li = document.createElement("li"); li.innerText = Math.floor(Math.random() * total); fragment.appendChild(li); } ul.appendChild(fragment); countOfRender += 1; loop(); } function loop() { if (countOfRender < loopCount) { window.requestAnimationFrame(add); } } loop(); }, 0); </script> </body> </html>
|
参考文档:https://www.jianshu.com/p/60f77d1a7d13