如何使用 JavaScript 将所有 HTML 元素子元素移动到另一个父元素?

IT技术 javascript html dom-manipulation
2021-02-20 04:14:19

想象:

<div id="old-parent">
    <span>Foo</span>
    <b>Bar</b>
    Hello World
</div>
<div id="new-parent"></div>

可以编写什么 JavaScript 来在没有 jQuery 的情况下将所有子节点(元素和文本节点)从old-parent到移动new-parent

我不关心节点之间的空白,尽管我希望能捕获这些杂散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>
5个回答

基本上,您希望遍历旧父节点的每个直接后代,并将其移动到新父节点。任何直系后代的孩子都会被它感动。

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>

外部链接

请注意, childNodes[] 通常也包含空文本节点(源代码中的每个换行符一个)。
2021-04-22 04:14:19
如果您追求性能,使用 DocumentFragment developer.mozilla.org/en-US/docs/Web/API/DocumentFragment并一次移动所有元素可能会有所帮助
2021-04-28 04:14:19
while (oldParent.hasChildNodes()) newParent.appendChild(oldParent.firstChild);while (oldParent.firstChild) newParent.appendChild(oldParent.firstChild);工作在2倍和铬快6倍至10倍的Firefox快。你修改后的 JSPerf
2021-05-02 04:14:19
@Gibolt 我创建了一个JSPerf测试,它似乎表明数组访问比调用firstChild. 这种差异充其量可以忽略不计。它也可能因浏览器而异。不过,我认为firstChild更具可读性。
2021-05-06 04:14:19
要真正高效: while (oldParent.childNodes.length) { newParent.appendChild(oldParent.firstChild); }
2021-05-15 04:14:19

现代方式:

newParent.append(...oldParent.childNodes);
  1. .append是 的替代品.appendChild主要区别在于它一次接受多个节点,甚至是纯字符串,例如.append('hello!')
  2. oldParent.childNodes可迭代的,因此可以传播...为多个参数.append()

两者的兼容性表(简称:Edge 17+,Safari 10+):

如果有,它必须是最小的。如果有的话,它会更快,因为它是一次append 调用而不是多次调用。
2021-04-24 04:14:19
看起来非常优雅。我想知道这里的其他答案是否存在性能差异。
2021-05-05 04:14:19
不错,但我做了一些简单的测试,while()在 Chrome 中仍然稍微快一些如果可能的话,不要相信我的话,并进行自己的测试。
2021-05-05 04:14:19
请注意:不适用于 IE11(从不,可能)
2021-05-07 04:14:19

这是一个简单的函数:

function setParent(el, newParent)
{
    newParent.appendChild(el);
}

elchildNodes要移动的元素, 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);
}

这是演示

@crush 看看编辑,sry - while (document.getElementById('old-parent').length > 0) { setParent(document.getElementById('old-parent')[i], document.getElementById('new-parent')); }
2021-04-19 04:14:19
这也行不通,因为当您移动孩子时,长度会发生变化。因此,您最终只会移动一半的节点。您需要向后迭代,或者像我一样使用 while 循环。
2021-04-24 04:14:19
您将如何将其与他的代码一起使用?这将移动old-parent,如果你通过了过于元素el
2021-04-30 04:14:19
还是不行。你需要做:for (var i = l; i >= 0; i--)while (document.getElementById('old-parent').length > 0)此外,您的演示中有错误。
2021-05-02 04:14:19
这将呈现 HTML: <div id="new-parent"><div id="old-parent">...</div></div>
2021-05-12 04:14:19

如果您不在-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>

仅当您除了将内部代码 (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 = '';

希望这可以帮助!

它不会复制附加到元素的任何对象和事件
2021-04-29 04:14:19
这有效,尽管我真的不想通过 HTML 字符串序列化/反序列化。不过它确实有效:)
2021-05-10 04:14:19
这会重新生成 DOM,它不会移动现有的节点/事件,而且它可能比所有子节点上的循环慢得多
2021-05-13 04:14:19
我运行了一些简单的测试,但这种方法仍然比接受的答案慢,并且它有已经解释过的缺点。
2021-05-16 04:14:19