大量DOM操作的解决方案

案例:如何在页面元素ul中一次性插入30000个li标签,保证页面体验流畅呢?

解决方案:可以从减少 DOM 操作次数、缩短循环时间两个方面减少主线程阻塞的时间

  • 减少 DOM 操作次数的良方是 DocumentFragment
  • 缩短循环时间需要考虑使用分治的思想把 30000 个 <li> 分批次插入到页面中,每次插入的时机是在页面重新渲染之前,采用 requestAnimationFrame 

代码示例:

(() => {
    const ndContainer = document.getElementById('js-list');
    if (!ndContainer) {
        return;
    }

    const total = 30000;
    const batchSize = 4; // 每批插入的节点次数,越大越卡
    const batchCount = total / batchSize; // 需要批量处理多少次
    let batchDone = 0;  // 已经完成的批处理个数

    function appendItems() {
        const fragment = document.createDocumentFragment();
        for (let i = 0; i < batchSize; i++) {
            const ndItem = document.createElement('li');
            ndItem.innerText = (batchDone * batchSize) + i + 1;
            fragment.appendChild(ndItem);
        }

        // 每次批处理只修改 1 次 DOM
        ndContainer.appendChild(fragment);

        batchDone += 1;
        doBatchAppend();
    }

    function doBatchAppend() {
        if (batchDone < batchCount) {
            window.requestAnimationFrame(appendItems);
        }
    }

    // 执行
    doBatchAppend();

    ndContainer.addEventListener('click', function (e) {
        const target = e.target;
        if (target.tagName === 'LI') {
            alert(target.innerHTML);
        }
    });
})();

 

posted @ 2018-05-04 16:33  奔跑的蜗牛~  阅读(1643)  评论(0编辑  收藏  举报