理解 DocumentFragment

龍恩0707發表於2017-09-02

理解 DocumentFragment

含義:建立文件片段,它繼承了Node的所有方法,對DOM操作效能非常好。
建立文件片段 如下方法:

var frag = document.createDocumentFragment();

文件片段有三個node屬性,nodeType, nodeName, nodeValue; 他們的值分別是 11, '#document-fragment', null, 文件片段節點沒有父節點parentNode. 如下程式碼演示:

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

它有什麼作用呢?
我們經常使用js來操作DOM操作,比如向頁面中插入元素,每次插入元素的時候,瀏覽器會發生重繪,都需要重新渲染頁面,如果做大量的這樣的操作,非常影響效能的,影響使用者體驗。
比如如下程式碼:

var ul = document.getElementById("ulId");
for (var i = 0; i < 30; i++) {
   var li = document.createElement('li');
   li.innerHTML = "aaa" + i;
   ul.appendChild(li)
 }

我們知道每一次插入都會引起重新渲染(計算元素的尺寸,顯示內容等),會重新重繪頁面,因此會影響效能的,我們最常見還有一種方法是將建立的元素寫到一個字串上,然後一次性寫到innerHTML上,這種使用瀏覽器對innerHTML的解析比上面多次插入快很多,但是構造字串靈活性比較差,很難符合建立各種各樣的DOM元素。如下程式碼:

var ul = document.getElementById("ulId");
var ihtml = '';
for (var i = 0; i < 30; i++) {
  ihtml += '<li>'+i+'</li>';
}
ul.innerHTML = ihtml;

但是使用DocumentFragment,可以彌補上面兩種方法的不足。
DocumentFragment是沒有父節點的最小文件物件,常用於儲存html和xml文件,它繼承了Node,因此它有Node的所有屬性和方法,完全可以操作Node那樣操作DocumentFragment.

DocumentFragment文件片段是存在於記憶體中的,沒有在DOM中,所以將子元素插入到文件片段中不會引起頁面迴流,因此使用DocumentFragment可以起到效能優化作用。
比如上面插入的程式碼可以改成如下:

<!DOCTYPE html>
 <html>
  <head>
    <meta charset="utf-8">
    <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta content="black" name="apple-mobile-web-app-status-bar-style">
    <meta content="telephone=no" name="format-detection">
    <meta content="email=no" name="format-detection">
    <title>標題</title>
    <link rel="shortcut icon" href="/favicon.ico">
  </head>
  <body>
    <ul id="ulId"></ul>
    <script>
     var ul = document.getElementById("ulId");
     var frag = document.createDocumentFragment();
     var ihtml = '';
     for (var i = 0; i < 30; i++) {
       var li = document.createElement('li');
       li.innerHTML = "index: " + i;
       frag.appendChild(li);
     }
     ul.appendChild(frag);
    </script>
  </body>
</html>