JavaScriptを使用してすべてのHTML要素の子を別の親に移動するにはどうすればよいですか?


80

想像してみてください:

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

JavaScriptはからすべての子ノード(両方の要素、およびテキストノード)を移動するために書き込むことができますどのようold-parentnew-parentjQueryをせずに?

ノード間の空白は気にしませんが、迷子をキャッチすることを期待していますが、ノードも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>


6
@MarcB、これは重複ではありません。あなたが移動を扱っていないためにリンクして、質問のすべて(そのようなテキストノードなど)の子どもを、またその質問アドレスHTMLノードの種類を移動するための私の必要性上の任意の答えを行います
ドリューNoakes

2
答えはまさにあなたが必要とするものです。domは木です。1つのノードを移動すると、そのノードのすべての子が一緒に移動します。
マークB

@MarcBは、宛先に親オブジェクトを配置したくない場合があります。たとえば、TODOリストのすべての要素を「保留中」から「完全な」親要素に移動することを検討してください。
ドリューノアケス

回答:


124

デモ

基本的に、古い親ノードの直接の子孫をループして、新しい親に移動します。直系の子孫は誰でも一緒に移動します。

var newParent = document.getElementById('new-parent');
var oldParent = document.getElementById('old-parent');

while (oldParent.childNodes.length > 0) {
    newParent.appendChild(oldParent.childNodes[0]);
}

8
本当に効率的にするために: while (oldParent.childNodes.length) { newParent.appendChild(oldParent.firstChild); }
Gibolt 2015

4
childNodes []には通常、空のテキストノードも含まれていることに注意してください(ソースコードの改行ごとに1つ)。
Dercsár

5
@Gibolt JSPerfテストを作成しましたが、配列へのアクセスがを呼び出すよりも速いことを示しているようfirstChildです。違いはせいぜいごくわずかです。おそらくブラウザによっても異なります。でもfirstChild、もっと読みやすいと思います。
2015

17
while (oldParent.hasChildNodes()) newParent.appendChild(oldParent.firstChild);そしてwhile (oldParent.firstChild) newParent.appendChild(oldParent.firstChild);仕事速いFirefoxで10倍に高速化クロムおよび6xで2倍。変更したJSPerf–
ユーザー

3
ドキュメント・使用することが有益であるかもしれないdeveloper.mozilla.org/en-US/docs/Web/API/DocumentFragmentを、あなたは、パフォーマンスの後にある場合は、一度にすべての要素を移動します。
Íhor私

10

現代的な方法:

newParent.append(...oldParent.childNodes);
  1. .appendの代わりになり.appendChildます。主な違いは、一度に複数のノードを受け入れ、次のような単純な文字列も受け入れることです。.append('hello!')
  2. oldParent.childNodesある反復可能と広げることができるので...、複数のパラメータになるために.append()

両方の互換性テーブル(要するに:Edge 17以降、Safari 10以降):


とてもエレガントに見えます。ここで他の答えとパフォーマンスの違いがあるのだろうか。
ドリューノアケス

ある場合、それは最小限でなければなりません。どちらかといえば、それappend は多くではなく単一の呼び出しであるため、より高速です。
fregante

警告:IE11用ではありません(おそらく決して)
Rene van

いいですが、私はいくつかの簡単なテストを行いましたwhile()が、Chromeではまだ少し高速です。私の言葉を信じないで、可能であれば独自のテストを実行してください。
レペ

8

簡単な関数は次のとおりです。

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

これがデモです


これを彼のコードでどのように使用しますか?これold-parentをとして渡した場合、要素も移動しますel
2014年

1
これは、HTMLをレンダリングします:<div id="new-parent"><div id="old-parent">...</div></div>
ときめき

1
子供を動かすと長さが変わるので、それもうまくいきません。したがって、ノードの半分だけを移動することになります。逆方向に繰り返すか、私が行ったようにwhileループを使用する必要があります。
2014年

それでも動作しません。あなたがする必要があります:for (var i = l; i >= 0; i--)またはwhile (document.getElementById('old-parent').length > 0)。また、デモにエラーがあります。
2014年

編集で@crush見て、SRY -while (document.getElementById('old-parent').length > 0) { setParent(document.getElementById('old-parent')[i], document.getElementById('new-parent')); }
Cilan

0

この答えは、内部コード(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 = '';

お役に立てれば!


1
これは機能しますが、HTML文字列を介してシリアル化/逆シリアル化する必要はありません。
それでも

11
要素に添付されたオブジェクトやイベントはコピーされません
Gregory Magarshak 2014

4
この再生成されたDOMは、既存のノード/イベントを移動せず、おそらくすべての子のループよりもはるかに低速です
ジョーダン

私はいくつかの簡単なテストを実行しましたが、この方法はまだ受け入れられた答えよりも遅く、すでに説明したように欠点があります。
レペ

-1

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.