Javascript 为什么在附加documentFragment时需要使用cloneNode?

Javascript 为什么在附加documentFragment时需要使用cloneNode?,javascript,dom,backbone.js,documentfragment,Javascript,Dom,Backbone.js,Documentfragment,我一直在研究如何在Backbone.js应用程序中使用documentFragments,我想知道为什么在将documentFragments附加到父DOM元素时会看到使用“cloneNode”的示例 可以看到一个例子。如果您往下看DocumentFragment部分,您将看到: oFrag = document.createDocumentFragment(); for (var i = 0, imax = aElms.length; i < imax; i++) { oFrag.ap

我一直在研究如何在Backbone.js应用程序中使用documentFragments,我想知道为什么在将documentFragments附加到父DOM元素时会看到使用“cloneNode”的示例

可以看到一个例子。如果您往下看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=document.createDocumentFragment(); 对于(var i=0,imax=aElms.length;i
为什么要克隆“oFrag”而不是仅仅附加它?另一个不使用“cloneNode”(作为比较)。

我不太确定,但是在您提供的链接(性能测试)的上下文中,rag.cloneNode(true)可能是一种保护措施,防止重用在以前的循环运行中已经添加到DOM中的元素,这将导致更快地执行测试


我认为没有理由在DocumentFragment的正常用例中使用它。

我认为没有必要。我猜它只是用来将
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);
var of rag=document.createDocumentFragment();
对于(var i=0,imax=aElms.length;i
虽然它可能比在整个片段上只调用一次要慢,因为节点树是用本机代码递归的

还请检查:-)

您的引用是自动程序使用
document.getElementsByTagName
而不是
document.getElementById
的位置,就像在测试用例中一样。如果要为多个元素(即:div)提供相同的
documentFragment
,则必须克隆它:

如果子节点是对文档中现有节点的引用,则appendChild会将其从当前位置移动到新位置(即,在将该节点附加到其他节点之前,无需将其从父节点移除)

这也意味着一个节点不能同时位于文档的两个点上。因此,如果节点已经有父节点,则首先将其删除,然后将其附加到新位置

通过

很可能是作者(或其他人)复制粘贴了代码而没有考虑到这一点。您可以自己尝试—您可以使用
appendChild
,而不使用
cloneNode
,一切正常

另一种可能性是,在jsperf上创建此测试用例的人不太了解准备代码的工作原理,并且担心第一次测试将清空
aElms
数组,它将不再工作。准备代码在每次定时迭代之前执行,所以不必担心它的内容

最后一件事可能是性能问题。如果确实要测试实际插入,则需要克隆节点。否则,您将测试tree重新连接(参见上面的MDN链接)

也请注意


快乐的碎片!;)

如果将documentFragment附加到元素中,然后从该元素中清除附加的节点,则documentFragment也将为空,无法再重复使用!附加documentFragment的克隆可以防止这种情况,并允许多次重用documentFragment

我假设jsperf代码段的作者正在测试这种情况

示例:具有父子关系的下拉列表。假设您有一个下拉列表,其中选择了一个大陆,第二个下拉列表列出了该大陆上的所有国家。如果要在创建后使用选项节点缓存创建的documentFragments,则需要使用cloneNode。想象一下,有人选择了欧洲,然后是非洲,然后又选择了欧洲:你可以重新创建整个文档片段,当然是缓存

我创建了一个jsperf片段来说明重新创建documentFragments与缓存和克隆片段的性能差异:


+1,确实很有趣。我唯一(也是相当疯狂)的猜测是,
cloneNode
的使用使我们能够更好地控制RAG
范围。我认为这不值得伪造成一个完整的答案,但无论如何。。。只需查找“documentFragment cloneNode”,我就找到了John Resig。)在本文的主题中,应该多次将一组节点插入DOM,因此克隆documentFragment确实是一个更好的选择。