zoukankan      html  css  js  c++  java
  • 页面加载海量数据优化方案

    题目:10w 条记录的数组,一次性渲染到页面上,如何处理可以不冻结UI?

    页面上有个空的无序列表节点 ul ,其 id 为 list-with-big-data ,现需要往列表插入 10w 个 li ,每个列表项的文本内容可自行定义,且要求当每个 li 被单击时,通过 alert 显示列表项内的文本内容。

    <!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>页面加载海量数据</title>
    </head>
    
    <body>
      <ul id="list-with-big-data">100000 数据</ul>
      <script>
        // 此处添加你的代码逻辑
      </script>
    </body>
    </html>

    分析:我们可以从 减少 DOM 操作次数 和 缩短循环时间 两个方面减少主线程阻塞的时间。

      可以通过 DocumentFragment 的使用,减少 DOM 操作次数,降低回流对性能的影响。

      在缩短循环时间方面,我们可以通过 分治 的思想,将 100000 个 li 分批插入到页面中,并且我们通过 requestAniminationFrame 在页面重绘前插入新节点。

    (function() {
      const ulContainer = document.getElementById("list-with-big-data");
    
      // 防御性编程
      if (!ulContainer) {
        return;
      }
    
      const total = 100000; // 插入数据的总数
      const batchSize = 4; // 每次批量插入的节点个数,个数越多,界面越卡顿
      const batchCount = total / batchSize; // 批处理的次数
      let batchDone = 0; // 已完成的批处理个数
    
      function appendItems() {
        // 使用 DocumentFragment 减少 DOM 操作次数,对已有元素不进行回流
        const fragment = document.createDocumentFragment();
    
        for (let i = 0; i < batchSize; i++) {
          const liItem = document.createElement("li");
          liItem.innerText = batchDone * batchSize + i + 1;
          fragment.appendChild(liItem);
        }
    
        // 每次批处理只修改 1 次 DOM
        ulContainer.appendChild(fragment);
        batchDone++;
        doAppendBatch();
      }
    
      function doAppendBatch() {
        if (batchDone < batchCount) {
          // 在重绘之前,分批插入新节点
          window.requestAnimationFrame(appendItems);
        }
      }
    
      // kickoff
      doAppendBatch();
    
      // 使用 事件委托 ,利用 JavaScript 的事件机制,实现对海量元素的监听,有效减少事件注册的数量
      ulContainer.addEventListener("click", function(e) {
        const target = e.target;
    
        if (target.tagName === "LI") {
          alert(target.innerText);
        }
      });
    })();
    
  • 相关阅读:
    懒加载与预加载
    Javascript之 Ajax 与 JSON
    Q&A:为什么prototype中的方法不能赋值给变量,再调用?
    Javascript之 浅克隆 与 深克隆
    Javascript之 __proto__ 与 prototype
    React入门(二)—— Props属性
    React入门(一)—— State属性
    Flask调用layer-iframe后,如何从服务器端关闭弹出窗
    Python从入门到项目实践(明日科技 吉林大学出版社)
    从实例到数理来解析感知机学习算法(PLA)
  • 原文地址:https://www.cnblogs.com/guoxianglei/p/8979066.html
Copyright © 2011-2022 走看看