createDocumentFragment()用法總結


1.createDocumentFragment()方法,是用來創建一個虛擬的節點對象,或者說,是用來創建文檔碎片節點。它可以包含各種類型的節點,在創建之初是空的。

2.DocumentFragment節點不屬於文檔樹,繼承的parentNode屬性總是null。它有一個很實用的特點,當請求把一個DocumentFragment節點插入文檔樹時,插入的不是DocumentFragment自身,而是它的所有子孫節點,即插入的是括號里的節點。這個特性使得DocumentFragment成了占位符,暫時存放那些一次插入文檔的節點。它還有利於實現文檔的剪切、復制和粘貼操作。 

另外,當需要添加多個dom元素時,如果先將這些元素添加到DocumentFragment中,再統一將DocumentFragment添加到頁面,會減少頁面渲染dom的次數,效率會明顯提升。

3.如果使用appendChid方法將原dom樹中的節點添加到DocumentFragment中時,會刪除原來的節點。 

4.createDocumentFragment()方法和createElement()方法的區別:

(1)需要很多的插入操作和改動,繼續使用類似於下面的代碼則會很有問題

var ul = document.getElementById("ul");
for (var i = 0; i < 20; i++) {
    var li = document.createElement("li");
    li.innerHTML = "index: " + i;
    ul.appendChild(li);

由於每一次對文檔的插入都會引起重新渲染(計算元素的尺寸,顯示背景,內容等),所以進行多次插入操作使得瀏覽器發生了很多次渲染,效率是比較低的。這是我們提倡通過減少頁面的渲染來提高DOM操作的效率的原因。一個優化的方法是將要創建的元素寫到一個字符串上,然后一次性寫到innerHTML上,這種利用瀏覽器對innerHTML的解析確實是相比上面的多次插入快了很多。但是構造字符串靈活性上面比較差,很難符合創建各種各樣的DOM元素的需求。利用DocumentFragment,可以彌補這兩個方法的不足。

因為文檔片段存在於內存中,並不在DOM中,所以將子元素插入到文檔片段中時不會引起頁面回流(對元素位置和幾何上的計算),因此使用DocumentFragment可以起到性能優化的作用。例如上面的代碼就可以改成下面的片段

var ul = document.getElementById("ul");
var fragment = document.createDocumentFragment();
for (var i = 0; i < 20; i++) {
    var li = document.createElement("li");
    li.innerHTML = "index: " + i;
    fragment.appendChild(li);
}
ul.appendChild(fragment);

(2)createElement創建的元素可以使用innerHTML,createDocumentFragment創建的元素使用innerHTML並不能達到預期修改文檔內容的效果,只是作為一個屬性而已。兩者的節點類型完全不同,createElement創建的是元素節點,節點類型為1,createDocumentFragment創建的是文檔碎片,節點類型是11。並且createDocumentFragment創建的元素在文檔中沒有對應的標記,因此在頁面上只能用js中訪問到。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <style type="text/css">
        #outer{ height: 200px; border: 1px solid #006400;}
    </style>
</head>
<body>
<div id="outer">
</div>
<input type="button" value="createElement" id="btn_1"/><input type="button" value="createDocumentFragment" id="btn_2"/>
<script type="text/javascript">
var fragment_1 = document.createDocumentFragment();
        fragment_1.innerHTML = '<p>我是一個粉刷匠</p>';
        document.body.appendChild(fragment_1);
    var fragment_2 = document.createElement('p');
        fragment_2.innerHTML = '粉刷本領強';
        document.body.appendChild(fragment_2);
</script>
</body>
</html>

(3)createElement創建的元素可以重復操作,添加之后就算從文檔里面移除依舊歸文檔所有,可以繼續操作,但是createDocumentFragment創建的元素是一次性的,添加之后再就不能操作了(說明:這里的添加並不是添加了新創建的片段,因為上面說過,新創建的片段在文檔內是沒有對應的標簽的,這里添加的是片段的所有子節點)。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <style type="text/css">
        #outer{ height: 200px; border: 1px solid #006400;}
    </style>
</head>
<body>
<div id="outer">
</div>
<input type="button" value="createElement" id="btn_1"/><input type="button" value="createDocumentFragment" id="btn_2"/>
<script type="text/javascript">
    function $(id){
        return document.getElementById(id);
    }
    var outer = $('outer');
    var inner = $('inner'); 
    $('btn_1').onclick = function(){
        var div = document.createElement('div');
            div.innerHTML = '<p>測試createElement</p>';
        document.body.appendChild(div);
        setTimeout(function(){
            outer.appendChild(div);
            setTimeout(function(){
                outer.removeChild(div);
            },1000)
        },1000)
    }
    $('btn_2').onclick = function(){
        var p = document.createElement('p');
            p.innerHTML = '測試DocumentFragment';
        var fragment = document.createDocumentFragment();
            fragment.appendChild(p);
            fragment.innerHTML = '<p>測試DocumentFragment</p>';
            fragment.innerHTML = '<span>測試DocumentFragment</span>';
        document.body.appendChild(fragment);
        setTimeout(function(){
            outer.appendChild(fragment);//報錯,因為此時文檔內部已經能夠不存在fragment了
            setTimeout(function(){
                outer.removeChild(fragment);
            },1000)
        },1000)
    }
</script>
</body>
</html>

(4)通過createElement新建元素必須指定元素tagName,因為其可用innerHTML添加子元素。通過createDocumentFragment則不必。

(5)通過createElement創建的元素插入文檔后,還可以取到創建時的返回值,即上面例子中createElement還是創建的那個div元素,而createDocumentFragment創建的元素插入到文檔后,就不能訪問創建時的返回值了,相當於把自己創建的文檔片段直接挪到文檔中了。

5.createDocumentFragment()方法和createElement()方法的共同點:

(1)添加子元素后返回值都是新添加的子元素,因此,可通過下面的方法利用innerHTML為createDocumentFragment添加子元素:

var fragment = document.createDocumentFragment();
var ret = fragment.appendChild(document.createElement('div'));
ret.innerHTML = 'by innerHTML ';
test1.appendChild(fragment);

(2)都可以通過appendChild添加子元素,且子元素必須是node類型,不能為文本。

(3)若添加的子元素是文檔中存在的元素,則通過appendChild在為其添加子元素時,會從文檔中刪除之前存在的元素。

6.DocumentFragment是沒有父節點的最小的文檔對象,用於存儲HTML和XML片段。DocumentFragment對象繼承Node,所以它有Node的所有屬性方法,完全可以操作Node(NodeList)那樣操作DocumentFragment。此外W3C對DocumentFragment也定義了一些另外的屬性和方法,但是由於多數瀏覽器都沒有實現,從兼容性上來說不推薦使用這些屬性。具體有哪些屬性方法可以參考MDN說明。

創建DocumentFragment的方法有兩種,document.createDocumentFragment()和new Fragment()。對於document.createDocumentFragment(),所有瀏覽器都支持(包括IE6),而構造函數方法就不是所有瀏覽器都有效了(IE沒有實現該方法)。所以從兼容性上來說推薦使用document.createDocumentFragment()。
---------------------
原文:https://blog.csdn.net/qiao13633426513/article/details/80243058


免責聲明!

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



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