頁面優化,DocumentFragment對象詳解


一、前言

最近項目不是很忙,所以去看了下之前總想整理的重匯和回流的相關資料,關於回流優化,提到了DocumentFragment的使用,這個對象在3年前我記得是有看過的,但是一直沒深入了解過,所以這里做個整理。后面會把重匯,回流也做個整理,不鴿。

二、DocumentFragment對象是什么?

MDN解釋:

DocumentFragment 表示一個沒有父級文件的最小文檔對象。它被當做一個輕量版的 Document 使用,用於存儲已排好版的或尚未打理好格式的XML片段。最大的區別是因為DocumentFragment不是真實DOM樹的一部分,它的變化不會引起DOM樹的重新渲染的操作(reflow) ,且不會導致性能等問題。---MDN

W3C解釋:

 DocumentFragment 接口表示文檔的一部分(或一段)。更確切地說,它表示一個或多個鄰接的 Document 節點和它們的所有子孫節點。 DocumentFragment 節點不屬於文檔樹,繼承的 parentNode 屬性總是 null。 不過它有一種特殊的行為,該行為使得它非常有用,即當請求把一個 DocumentFragment 節點插入文檔樹時,插入的不是 DocumentFragment 自身,而是它的所有子孫節點。這使得 DocumentFragment 成了有用的占位符,暫時存放那些一次插入文檔的節點。它還有利於實現文檔的剪切、復制和粘貼操作,尤其是與 Range 接口一起使用時更是如此。 可以用 Document.createDocumentFragment() 方法創建新的空 DocumentFragment 節點。---W3C

怎么去理解呢?我們結合上面兩解釋可以得知,DocumentFragment 節點不屬於DOM樹,因此它的變化不會引起DOM樹的變化;

我們知道,DOM樹的操作會引起回流,那我們可以將DocumentFragment作為一個暫時的DOM節點存儲器,當我們在DocumentFragment 修改完成時,我們就可以將存儲DOM節點的DocumentFragment一次性加入DOM樹,從而減少回流次數,達到性能優化的目的。

三、DocumentFragment對象怎么用?

我們可以使用document.createDocumentFragment()創建一個DocumentFragment,每個新建的DocumentFragment都會繼承所有node方法。且DocumentFragment擁有nodeValue,nodeName,nodeType屬性。

let fragment =  document.createDocumentFragment();
console.log(fragment.nodeValue); //null
console.log(fragment.nodeName); //#document-fragment
console.log(fragment.nodeType); //11

使用DocumentFragment能解決直接操作DOM引發大量回流的問題,比如我們要給ul添加五個li節點,區別就像這樣:

直接操作DOM,回流五次:

使用DocumentFragment一次性添加,回流一次:

假設我們給ul加入五萬個li,分別對比下渲染完成時間:

html:
<body>
    <ul id="list"></ul>
    <ul id="list1"></ul>
</body>


js:
//使用documentFragment添加節點
console.time("time")
let list = document.querySelector("#list"),
    fragment = document.createDocumentFragment(),
    n = 50000;
while(n--){
  fragment.appendChild(document.createElement("li"));
};
list.appendChild(fragment);
console.timeEnd("time")

//直接操作DOM添加節點
console.time("time1")
let list1 = document.querySelector("#list1"),
    i = 50000;
while(i--){
  list1.appendChild(document.createElement("li"))
};
console.timeEnd("time1")

多刷新幾次對比兩者的耗時,time是使用了DocumentFragment的耗時,time1是直接添加DOM的耗時

很明顯,time比time1耗時要短很多。

再刷新幾次試試

很明顯,多次刷新反而還會出現使用DocumentFragment耗時更久的情況,性能更差?打臉了。暫時無法解釋,希望有大佬能說說。

不過讀到這,也明白了DocumentFragment是個什么東西,怎么使用它,那么本文就到這里結束了。

 

參考資料

深入理解DOM節點類型第四篇——文檔片段節點DocumentFragment

DocumentFragment對象


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM