如何渲染几万条数据不卡住页面?也就是说不能一次性将几万条数据都渲染出来,而是应该一次渲染一部分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