我想保存一个DOM子树(div下的所有内容,名为"框图")然后将它绘制在名为" bus_diagram"的div上。保存childNodes属性似乎不会出于某种原因捕获所有元素。
这是我正在使用的javascript。在调用函数" dostuff()" " block_diagram"应该去" bus_diagram"
var SAVED_BLOCK_DOM = null;
function save_block() {
SAVED_BLOCK_DOM = document.getElementById("block_diagram").childNodes;
}
function refresh_block() {
for (var i = 0; i < SAVED_BLOCK_DOM.length; i++) {
document.getElementById("bus_diagram").appendChild(SAVED_BLOCK_DOM[i]);
}
}
function dostuff() {
save_block();
refresh_block();
}
这是一个JSFiddle:http://jsfiddle.net/BFp5s/3/
答案 0 :(得分:1)
.childNodes
是节点的实时集合,当您开始在节点上执行.appendChild()时(将元素移动到DOM中的不同位置),实时集合会在您迭代时更改,导致您错过节点。因此,当您的for
循环的索引为0
时,您会在列表的.appendChild()
元素上执行0th
。这会从实时列表中删除该元素。然后,您将索引增加到1
,但下一个要处理的项目现在位于列表中的0th
位置,导致您处理其他所有项目。
您可以将实时列表的副本复制到一个数组中(因此在迭代时不会更改)或更改迭代列表的方式。
例如,您可以将save_block()
更改为:
function save_block() {
SAVED_BLOCK_DOM = Array.prototype.slice.call(document.getElementById("block_diagram").childNodes, 0);
}
这会使SAVED_BLOCK_DOM
成为正常数组,因此在迭代时它不会改变。
jsFiddle演示:http://jsfiddle.net/jfriend00/R8c94/
或者,如果您需要/需要支持IE6 / 7/8支持,这对于上述复制机制不起作用,您可以手动复制nodeList:
function save_block() {
SAVED_BLOCK_DOM = [];
var list = document.getElementById("block_diagram").childNodes;
for (var i = 0; i < list.length; i++) {
SAVED_BLOCK_DOM.push(list[i]);
}
}
如果您不需要SAVED_BLOCK_DOM
继续保留节点列表并希望支持IE8,您可以像这样更改迭代方式:
function refresh_block() {
while (SAVED_BLOCK_DOM.length) {
document.getElementById("bus_diagram").appendChild(SAVED_BLOCK_DOM[0]);
}
}
jsFiddle演示:http://jsfiddle.net/jfriend00/PK7Tg/