我发誓几天前工作正常......
elm = document.querySelectorAll(selector);
var frag = document.createDocumentFragment();
while (elm[0]){
frag.appendChild(elm[0]);
}
是的,所以,这应该从我们的elm
节点列表中追加每个节点。当第一个被追加时,第二个“移动”到节点列表中的第一个位置,因此下一个始终是elm[0]
。当elm
nodeList被完全追加时,应该停止。然而,这给了我一个无限循环。想法?
编辑 - 因为我已多次得到相同的答案......
nodeList
不是数组,它是实时引用。当一个节点被“移动”(这里,附加)时,它应该从节点列表中自动删除。答案都说“你一遍又一遍地追加相同的元素” - 这就是发生的事情,不应该。 for循环不应该工作,因为当附加第一个节点时,下一个节点将获取其索引。
第二次编辑
所以现在的问题是“为什么nodeList
表现为数组?”。每次在某处添加节点时,节点列表应该都要更新。最奇特的。
解决方案(如果有人需要处理实时+非实时节点列表的内容)
elm = (/*however you're getting a node list*/);
var frag = document.createDocumentFragment();
var elength = elm.length;
for (var b = 0; b<elength; b++){
if (elm.length === elength){
frag.appendChild(elm[b]);
} else {
frag.appendChild(elm[0].cloneNode());
}
}
基本上,只需检查节点列表是否已更改长度。
答案 0 :(得分:4)
来自MDN Docs
返回从调用它的元素的所有元素的 非实时NodeList ,该元素与指定的CSS选择器组匹配。
elementList = baseElement.querySelectorAll(selectors);
,其中
elementList
是元素对象的非实时列表。baseElement
是一个元素对象。selectors
是一组要匹配的选择器。从上面的文档中,您可以看到,当您将其附加到另一个元素时,它不会自动将其删除,因为它不是实时的。运行演示以显示该功能。
var selector = "div";
elm = document.querySelectorAll(selector);
var frag = document.createDocumentFragment();
console.log("before",elm.length);
frag.appendChild(elm[0]);
console.log("after",elm.length);
当上面的代码运行时,你会在控制台中获得。
before 3
after 3
如果你想做while循环,转换为数组并关闭()项目
var selector = "div";
var elmNodeLIst = document.querySelectorAll(selector);
var frag = document.createDocumentFragment();
var elems = Array.prototype.slice.call(elmNodeLIst );
while (elems.length) {
frag.appendChild(elems.shift());
}
console.log(frag);
答案 1 :(得分:1)
您要在节点列表中追加第一项,一遍又一遍。您永远不会从数组中删除任何项目,但始终将第一个项目添加到片段中。而第一个总是一样的。
elm = document.querySelectorAll(selector);
var frag = document.createDocumentFragment();
while (elm.length){
frag.appendChild(elm.shift());
}
这可能更接近你的意图。我们可以使用while (elm.length)
,因为当项目从数组中删除时,最终长度将为零,这是一个眩光值,循环将停止。
我们使用elm.shift()
从数组中获取项目,因为该方法将返回索引为零的项目并将其从数组中删除,从而为我们提供了所需原始数组的变异。
我认为你认为这可能有效,因为一个节点只能有一个父节点。添加某处的含义将其从上一个父项中删除。但是,elm
不是 DOM片段。它只是一个包含元素引用的aray(或者可能是NodeList)。该数组不是这些元素的父节点,它只保存引用。
如果您有这样的循环可能会有效,因为您每次都要查询父节点的子节点,这是一个在您移动时实际会发生变化的节点列表:
elm = document.getElementById(id);
var frag = document.createDocumentFragment();
while (elm.children[0]){
frag.appendChild(elm.children[0]);
}
答案 2 :(得分:0)
我不希望它首先发挥作用。
您的elm
数组已初始化,且从未更新过。即使运行document.querySelectorAll(selector);
的结果会返回不同的结果,也不会更改数组中的当前引用。
您需要重新运行选择器,或者在追加它后手动删除数组中的第一个元素。
答案 3 :(得分:0)
它是一个无限循环,因为它现在被写入,因为elm[0]
总是引用相同的元素,并且该元素永远不为null(任何非null /非零结果都为真)。您也不对元素本身执行任何操作以使其在列表中进行迭代。您应该使用for循环而不是一段时间或者至少使用某种索引器来尝试遍历集合。
elm = document.querySelectorAll(selector);
var frag = document.createDocumentFragment();
for (i= 0; i < elm.length; i++)
{
frag.appendChild(elm[i]);
}
修改强>
“现场”收藏
在大多数情况下,NodeList是一个实时集合。这意味着DOM树&gt;的更改将反映在集合中。
var links = document.getElementsByTagName('a'); // links.length === 2例如
document.body.appendChild(links [0] .cloneNode(true)); //将另一个链接添加到文档中 //'链接'NodeList自动更新
// links.length === 3现在。如果NodeList是document.querySelectorAll的返回值,则它是 NOT live。
根据此文档,您当前使用的方法表明您没有实时NodeList。因此,追加将永远不会修改原始列表。您需要在循环中修改您的用法以反映.cloneNode(true)
的使用情况或手动迭代。
答案 4 :(得分:0)
elm [0]在上面的代码中是静态且不变的 修复如下
elm = document.querySelectorAll(".container");
var frag = document.createDocumentFragment();
console.log(elm);
var i=0;
while (elm[i]){
frag.appendChild(elm[i++]);
}
答案 5 :(得分:0)
我实际上并没有太多关注代码(如果它有意义 - 从评论中判断 - 或者不是);但如果这几天前有效,那么问题出在你给代码选择器的输入中。
单位测试就派上用场了。如果您能记住代码工作的输入,那么您可以再次使用它并从那里开始调试。
否则,你只是骗自己。