2012-12-13 51 views
7

我一直在尋找在Backbone.js應用程序中使用documentFragments,並想知道爲什麼我會在將documentFragment附加到父DOM元素時使用「cloneNode」。爲什麼在追加documentFragment時需要使用cloneNode?

可以看到一個例子here。如果您在DocumentFragment的部分往下看,你會看到:

oFrag = document.createDocumentFragment(); 
for (var i = 0, imax = aElms.length; i < imax; i++) { 
oFrag.appendChild(aElms[i]); 
} 

o.innerHTML = ''; 
o.appendChild(oFrag.cloneNode(true)); 

爲什麼「oFrag」被克隆而不是隻追加了嗎?另一個blog post不使用「cloneNode」(作爲比較)。

+0

+1,確實很有意思。我唯一的(也是非常瘋狂的)猜測是'cloneNode'的使用使我們可以更好地控制'oFrag'範圍。 – raina77ow

+0

我認爲這不應該被僞造成一個完整的答案,但無論如何...只要通過尋找'documentFragment cloneNode'我已經找到[這篇文章](http://ejohn.org/blog/dom-文件片段/)John Resig。 )在這篇文章的主題中,應該將一堆節點插入到DOM_several_ times中,因此克隆documentFragment確實是一個更好的選擇。 – raina77ow

回答

5

first linkblog post在作者日期使用document.getElementsByTagName代替document.getElementById,就像在測試用例。如果你想多元素(即:申報單),給予相同的documentFragment,你必須克隆它:如果孩子對文檔中的現有節點的引用

,使用appendChild移動它從當前位置到新的位置(即,不需要在將節點附加到其他節點之前從其父節點移除節點)。

這也意味着一個節點不能同時在文檔的兩個點上。所以如果節點已經有父節點,它首先被刪除,然後附加到新的位置。

通過 MDN

最有可能

作者(或其他人)複製粘貼代碼沒有考慮到這一點。嘗試一下 - 你可以使用appendChild而不用cloneNode,一切正常。

另一種可能性是,在jsperf上創建這個測試用例的人沒有太多的準備代碼的工作原理,並擔心第一次測試將清空aElms數組,並且它將不再工作。 In fact準備代碼在每次定時迭代之前執行,因此無需擔心其內容。

性能問題可能是最後一件事。如果您真的想測試實際插入,則需要克隆該節點。否則,您將替代測試樹重新附件(請參閱上面的MDN鏈接)。請注意0​​。

快樂碎片'! ;)

2

我並不完全確定,但在您提供的鏈接(性能測試)中,oFrag.cloneNode(true)可能是防止在之前的循環運行中重複使用DOM中已添加的元素,這會導致更快地執行測試。

我看不到在documentFragments的正常使用情況下使用它的理由。

+0

+1我想這是確實的原因。 – raina77ow

0

我不認爲這是必要的。我想它只是用來將aElms從靜態引用中分離出來,在調用appendChild時,它們需要從其父母中刪除。這只是在這個測試中的性能。

但是,下面的代碼(更類似於appendChild測試)會更有意義對我說:

var oFrag = document.createDocumentFragment(); 
for (var i = 0, imax = aElms.length; i < imax; i++) 
    oFrag.appendChild(aElms[i].cloneNode(true)); 
// using it here:    ^^^^^^^^^^^^^^^^ 
o.appendChild(oFrag); 

雖然它可能會比調用它只能對整個片段,其中節點樹一旦慢使用本機代碼進行遞歸。

還檢查了http://jsperf.com/cloning-fragments :-)

2

如果將一個documentFragment附加到一個元素,並且稍後清除該元素的附加節點,那麼documentFragment也將爲空,並且不能再使用!追加你的documentFragment的克隆可以防止這種情況,並允許多次重複使用你的documentFragment。

我假設jsperf snippet的作者正在測試這種情況。

示例:帶有父子關係的下拉菜單。假設您有一個下拉菜單,您可以選擇一個大洲,第二個下拉菜單列出該大陸所有國家。如果您想要在創建後將創建的documentFragments與選項節點一起緩存,則需要使用cloneNode。想象一下,有人選擇了歐洲,然後是非洲,然後是歐洲:您可以重新創建緩存它的整個文檔片段。

我創建了一個jsperf片段闡述重現documentFragments VS緩存和克隆片段的性能差異:

http://jsperf.com/documentfragment-cache-vs-recreate

+0

感謝您提供的信息,這非常有趣。 – codecraig

相關問題