如何使用 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);

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);

Here is the Demo

【讨论】:

你会如何使用他的代码?如果您将 old-parent 元素作为 el 传递,这也会移动 old-parent 元素。 这将呈现 HTML:&lt;div id="new-parent"&gt;&lt;div id="old-parent"&gt;...&lt;/div&gt;&lt;/div&gt; 这也行不通,因为当您移动孩子时,长度会发生变化。因此,您最终只会移动一半的节点。您需要向后迭代,或者像我一样使用 while 循环。 还是不行。您需要这样做:for (var i = l; i &gt;= 0; i--)while (document.getElementById('old-parent').length &gt; 0)。此外,您的演示中有错误。 @crush 看看编辑,对不起 - while (document.getElementById('old-parent').length &gt; 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.childNodesiterable 所以它可以和... 一起传播成为.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 打开另一个 HTML 页面

验证后如何使用 JavaScript 和 HTML5 将图像放在单选按钮上

如何使用 C# 执行 HTML 文件的所有 Javascript 以仅生成 HTML DOM

如何使用 javascript 或 jquery 仅从字符串中获取所有 HTML 标记? [关闭]

如何使用 Javascript 获取选定文本中的所有 HTML 选择标签?