1. 程式人生 > >頁面海量資料優化載入

頁面海量資料優化載入

要求:將10W條資料一次渲染到頁面上?

分析:
·資料量過大,出現卡頓感的主要原因是,在每次迴圈中,都會修改 DOM 結構,並且由於資料量大,導致迴圈執行時間過長,瀏覽器的渲染幀率過低。
·從 減少 DOM 操作次數 和 縮短迴圈時間 兩個方面減少主執行緒阻塞的時間.
·通過 DocumentFragment 的使用,減少 DOM 操作次數,降低迴流對效能的影響;
·在縮短迴圈時間方面,我們可以通過 分治 的思想,將 100000 個 li 分批插入到頁面中,並且我們通過 requestAniminationFrame 在頁面重繪前插入新節點。

DocumentFragment節點不屬於文件樹,繼承的parentNode屬性總是null。它有一個很實用的特點,當請求把一個DocumentFragment節點插入文件樹時,插入的不是DocumentFragment自身,而是它的所有子孫節點。這個特性使得DocumentFragment成了佔位符,暫時存放那些一次插入文件的節點。

HTML:

<ul id="oUl"></ul>

JS:

(function () {
    const oUl = document.getElementById("oUl");

    //防禦性程式設計
    if(!oUl){
        return;
    }

    const total = 10000;    //插入資料的總數
    const size = 4;         //每次批量插入的節點數,個數越多,頁面越卡頓
    const count = total/size;   //批處理的次數
    let num = 0;            //完成處理的次數

    //往列表插入 10w 個 li ,每個列表項的文字內容可自行定義
    function appendItems() {
        //使用 DocumentFragment 減少 DOM 操作次數,對已有元素不進行迴流
        const fragment = document.createDocumentFragment('li');

        for(let i=0;i<size;i++){
            const li = document.createElement("li");
            li.innerText = num * size + i + 1;
            fragment.appendChild(li);
        }

        //每次批處理只修改一次DOM
        oUl.appendChild(fragment);
        num++;
        doAppendBatch();
    }

    function doAppendBatch(){
        if(num < count){
            window.requestAnimationFrame(appendItems);    // 在重繪之前,分批插入新節點
        }
    }

    doAppendBatch();

    //要求當每個 li 被單擊時,通過 alert 顯示列表項內的文字內容
    //使用 事件委託 ,利用 JavaScript 的事件機制,實現對海量元素的監聽,有效減少事件註冊的數量
    oUl.addEventListener("click",function (e) {
        var e = e || window.event;    //相容IE
        const target = e.target || e.srcElement;
        if(target.nodeName.toUpperCase() === "LI")
            alert(target.innerText);
    })

})();