如何使用 JavaScript 将所有 HTML 元素子元素移动到另一个父元素?
Posted
技术标签:
【中文标题】如何使用 JavaScript 将所有 HTML 元素子元素移动到另一个父元素?【英文标题】:How to move all HTML element children to another parent using JavaScript? 【发布时间】:2014-01-21 12:09:18 【问题描述】:想象一下:
<div id="old-parent">
<span>Foo</span>
<b>Bar</b>
Hello World
</div>
<div id="new-parent"></div>
可以编写什么 javascript 来将所有子节点(包括元素和文本节点)从 old-parent
移动到 new-parent
而无需 jQuery?
我不关心节点之间的空白,虽然我希望能捕捉到流浪的Hello World
,但它们也需要按原样迁移。
编辑
明确地说,我想结束:
<div id="old-parent"></div>
<div id="new-parent">
<span>Foo</span>
<b>Bar</b>
Hello World
</div>
建议重复的问题的答案将导致:
<div id="new-parent">
<div id="old-parent">
<span>Foo</span>
<b>Bar</b>
Hello World
</div>
</div>
【问题讨论】:
"Cut and Paste" - moving nodes in the DOM with Javascript的可能重复 @MarcB,这不是重复的。您链接到的问题不涉及移动 all 子项,该问题的任何答案也没有解决我需要移动不同类型的 html 节点(例如文本节点)。 答案正是您所需要的。 dom 是一棵树。移动一个节点,该节点的所有子节点都会随之移动。 @MarcB 有时您不希望目标中的父对象。例如,考虑将 TODO 列表的所有元素从“待定”父元素移动到“完成”父元素。 【参考方案1】:这是一个简单的函数:
function setParent(el, newParent)
newParent.appendChild(el);
el
的childNodes
是要移动的元素, newParent
是将要移动到的元素el
, 所以你可以执行函数如下:
var l = document.getElementById('old-parent').childNodes.length;
var a = document.getElementById('old-parent');
var b = document.getElementById('new-parent');
for (var i = l; i >= 0; i--)
setParent(a.childNodes[0], b);
Here is the Demo
【讨论】:
你会如何使用他的代码?如果您将old-parent
元素作为 el
传递,这也会移动 old-parent
元素。
这将呈现 HTML:<div id="new-parent"><div id="old-parent">...</div></div>
这也行不通,因为当您移动孩子时,长度会发生变化。因此,您最终只会移动一半的节点。您需要向后迭代,或者像我一样使用 while 循环。
还是不行。您需要这样做:for (var i = l; i >= 0; i--)
或 while (document.getElementById('old-parent').length > 0)
。此外,您的演示中有错误。
@crush 看看编辑,对不起 - while (document.getElementById('old-parent').length > 0) setParent(document.getElementById('old-parent')[i], document.getElementById('new-parent'));
【参考方案2】:
这个答案只有在你不需要做任何事情的时候才真正有效,除了将内部代码(innerHTML)从一个转移到另一个:
// Define old parent
var oldParent = document.getElementById('old-parent');
// Define new parent
var newParent = document.getElementById('new-parent');
// Basically takes the inner code of the old, and places it into the new one
newParent.innerHTML = oldParent.innerHTML;
// Delete / Clear the innerHTML / code of the old Parent
oldParent.innerHTML = '';
希望这会有所帮助!
【讨论】:
这行得通,尽管我真的不想通过 HTML 字符串进行序列化/反序列化。它确实有效:) 它不会复制任何附加到元素的对象和事件 这会重新生成 DOM,它不会移动现有节点/事件,而且它可能比所有子节点上的循环要慢得多 我进行了一些简单的测试,但这种方法仍然比公认的答案慢,并且它有已经解释过的缺点。【参考方案3】:基本上,您希望遍历旧父节点的每个直接后代,并将其移动到新父节点。任何直系后代的子代都会随之移动。
var newParent = document.getElementById('new-parent');
var oldParent = document.getElementById('old-parent');
function move()
while (oldParent.childNodes.length > 0)
newParent.appendChild(oldParent.childNodes[0]);
#old-parent
background-color: red;
#new-parent
background-color: green;
<div id="old-parent">
<span>Foo</span>
<b>Bar</b> Hello World
</div>
<div id="new-parent"></div>
<br>
<button onclick="move()" id="button">Move childs</button>
External link
【讨论】:
要真正高效:while (oldParent.childNodes.length) newParent.appendChild(oldParent.firstChild);
注意,childNodes[] 通常也包含空文本节点(源代码中的每个换行符一个)。
@Gibolt 我创建了一个JSPerf 测试,它似乎表明数组访问比调用firstChild
更快。差异充其量可以忽略不计。它可能也会因浏览器而异。不过,我认为firstChild
更具可读性。
while (oldParent.hasChildNodes()) newParent.appendChild(oldParent.firstChild);
和 while (oldParent.firstChild) newParent.appendChild(oldParent.firstChild);
在 Chromium 中的运行速度提高了 2 倍,在 Firefox 中运行速度提高了 6 到 10 倍。 Your modified JSPerf
如果您追求性能,使用 DocumentFragment developer.mozilla.org/en-US/docs/Web/API/DocumentFragment 并一次移动所有元素可能会有所帮助。【参考方案4】:
如果你没有在 id 的名字中使用-
,那么你可以这样做
oldParent.id='xxx';
newParent.id='oldParent';
xxx.id='newParent';
oldParent.parentNode.insertBefore(oldParent,newParent);
#newParent color: red
<div id="oldParent">
<span>Foo</span>
<b>Bar</b>
Hello World
</div>
<div id="newParent"></div>
【讨论】:
【参考方案5】:现代方式:
newParent.append(...oldParent.childNodes);
.append
是 .appendChild
的替代品。主要区别在于它一次接受多个节点,甚至是纯字符串,比如.append('hello!')
oldParent.childNodes
是 iterable 所以它可以和...
一起传播成为.append()
的多个参数
两者的兼容性表(简称:Edge 17+、Safari 10+):
https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append#Browser_compatibility https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Browser_compatibility【讨论】:
看起来很优雅。我想知道这里的其他答案是否存在性能差异。 如果有,它必须是最小的。如果有的话,它会更快,因为它是单个append
调用而不是多个调用。
警告:不适用于 IE11(从不,可能)
很好,但我做了一些简单的测试,while()
在 Chrome 中仍然稍快一些。不要相信我的话,如果可能的话,请自己进行测试。以上是关于如何使用 JavaScript 将所有 HTML 元素子元素移动到另一个父元素?的主要内容,如果未能解决你的问题,请参考以下文章
如何将一个对象数组中的所有项目从Javascript动态显示为HTML?
验证后如何使用 JavaScript 和 HTML5 将图像放在单选按钮上
如何使用 C# 执行 HTML 文件的所有 Javascript 以仅生成 HTML DOM