为什么在添加后DocumentFragment被清除?

6
第一个日志返回完整的li元素,而第二个日志返回一个空的DocumentFragment。为什么?我在任何文档中都找不到关于这种行为的信息。

var main = document.getElementById('main');
var fooTemplate = document.getElementById('my-template');
var foo = fooTemplate.content.cloneNode(true);

console.log(foo);
main.appendChild(foo);
console.log(foo);
<template id="my-template">
    <li>foo</li>
</template>

<ul id="main">
</ul>

1个回答

6

关于 DocumentFragment 的 MDN 文档

其他一些方法可能会将文档片段作为参数(例如任何继承自 Node 接口的方法,如 Node.appendChildNode.insertBefore),这种情况下,将追加或插入文档片段的子元素,而不是文档片段本身。

foo = fooTemplate.content.cloneNode(true) 将文档片段复制到 foo

main.appendChild(foo)foo 文档片段中的内容移到了 main 中。此时,foo 仍然是一个文档片段,它内部的所有节点都已经移动,所以它现在为空。

如果你想在将节点添加到页面后仍然引用它们,请存储这些节点的 childNodes,但如果你只是引用 nodeList,那么它将为空,因此你需要将其转换为一个 Array

var nodes = Array.prototype.slice.call(foo.childNodes);
console.log(nodes);
main.appendChild(foo);
console.log(nodes);

好的,它仍然返回相同的结果... - Lithy
2
@Lithy,哦,我现在明白了。我说得太早了。fooTemplate.content.cloneNode(true)克隆文档片段。将文档片段附加到另一个元素会移动其内容,留下空的文档片段。 - zzzzBov
1
我认为你在这里不应该使用“复制”这个术语。它们要么是“移动”的,要么是“克隆”的。 - Bergi
1
有没有一种简单的方法来获取对新添加节点的引用?我有点惊讶... - Lithy
@Lithy,这就是为什么jQuery是如此受欢迎的库。 - zzzzBov
@Lithy,如果你使用了appendChild,你实际上可以从你添加它的节点中获得最后一个子节点。这非常清晰,因为你可以将这些东西放在一个函数中。请记住JS是单线程的,所以它不会造成任何问题。(除了在NodeJs中可能会有问题,但我不确定,在那里你也不会做太多DOM操作。) - David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接