大量DOM操做的解決方案

案例:如何在頁面元素ul中一次性插入30000個li標籤,保證頁面體驗流暢呢?

解決方案:能夠從減小 DOM 操做次數、縮短循環時間兩個方面減小主線程阻塞的時間app

  • 減小 DOM 操做次數的良方是 DocumentFragment
  • 縮短循環時間須要考慮使用分治的思想把 30000 個 <li> 分批次插入到頁面中,每次插入的時機是在頁面從新渲染以前,採用 requestAnimationFrame 

代碼示例:spa

(() => {
    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);
        }
    });
})();
相關文章
相關標籤/搜索