Javascript 为什么在附加documentFragment时需要使用cloneNode?
我一直在研究如何在Backbone.js应用程序中使用documentFragments,我想知道为什么在将documentFragments附加到父DOM元素时会看到使用“cloneNode”的示例 可以看到一个例子。如果您往下看DocumentFragment部分,您将看到: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
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确实是一个更好的选择。