JavaScriptで親要素のみを削除し、子要素は削除しない方法は?


88

まあ言ってみれば:

<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>

これに:

<div>
  pre text
  <p>child foo</p>
  <p>child bar</p>
  nested text
  post text
</div>

私はMootools、jQuery、さらには(生の)JavaScriptを使用して考えていましたが、これを行う方法を理解できませんでした。

回答:


138

jQueryを使用してこれを行うことができます:

var cnt = $(".remove-just-this").contents();
$(".remove-just-this").replaceWith(cnt);

ドキュメントへのクイックリンク:


私がこの3時間前に気づいた(エラーが見つかりました)...シンプルでエレガント-すごい!
Tathagata

3
「cnt」の意味は何ですか?
Steven Lu

1
'cnt'は「コンテンツ」を保持する変数名です
ジョージアンダーソン

1
理由はわかりませんが、contents()を使用している場合はうまくいきませんでした。しかし、contents()の代わりにhtml()を使用すると、魅力的に機能しました。
vertigoelectric 2012

たった1行のバージョン:$('.remove-just-this').replaceWith(function() { return $(this).html(); });
Taufik Nur Ra​​hmanda 2017

36

ライブラリに依存しない方法は、削除する要素のすべての子ノードをそれ自体の前に挿入して(暗黙的に古い位置からそれらを削除します)、削除する前に:

while (nodeToBeRemoved.firstChild)
{
    nodeToBeRemoved.parentNode.insertBefore(nodeToBeRemoved.firstChild,
                                            nodeToBeRemoved);
}

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

これにより、すべての子ノードが正しい順序で正しい場所に移動します。


3
現代のJSは、このサポートしていますnode.replaceWith(...node.childNodes);
Gibolt

34

イベントハンドラーなどを保持するために、DOMではなくこれを行う必要がありますinnerHTML(jkが提供するjQueryソリューションを使用する場合は、innerHTML内部で使用するのではなく、DOMノードを移動するようにしてください)。

私の答えはたくさんinsinのようなものですが、各ノードを追加する大規模な構造は(別途CSSがそれぞれに再適用する必要があります再描画に課税することができ、より良い実行しますappendChild。でDocumentFragment、それがその後まで見えるようにされていないなどと、これはのみ発生します子がすべて追加され、ドキュメントに追加されます)。

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

ありがとうございました; 短くて直接的。
brunoais


22

よりエレガントな方法は

$('.remove-just-this').contents().unwrap();

2
ベストアンサー。ありがとう。
user706420

7

最新のJSを使用してください!

const node = document.getElementsByClassName('.remove-just-this')[0];
node.replaceWith(...node.childNodes); // or node.children, if you don't want textNodes

oldNode.replaceWith(newNode) 有効なES5

...array 各配列要素をパラメータとして渡すスプレッド演算子です


2

使用しているどのライブラリでも、DOMから外側のdivを削除する前に、内側のdivを複製する必要があります。次に、クローンされた内側のdivを、外側のdivがあったDOMの場所に追加する必要があります。したがって、手順は次のとおりです。

  1. 外側のdivの親への参照を変数に保存する
  2. 内側のdivを別の変数にコピーします。これを保存することにより、迅速かつ汚い方法で行うことができますinnerHTMLは、内側のdivのを変数にでことができます。また、内側のツリーをノードごとに再帰的にコピーすることもできます。
  3. removeChild引数として外部divを使用して、外部divの親を呼び出します。
  4. コピーされた内部コンテンツを外部divの親の正しい位置に挿入します。

一部のライブラリは、これの一部またはすべてを実行しますが、上記のようなものが内部で行われます。



1

divをその内容に置き換えます。

const wrapper = document.querySelector('.remove-just-this');
wrapper.outerHTML = wrapper.innerHTML;
<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>


0

パジャマで同じことをしたい場合は、次のようにします。それは素晴らしい働きをします(まぶたに感謝します)。これのおかげで、めちゃくちゃにならずにスタイルを適切に処理する適切なリッチテキストエディターを作成できました。

def remove_node(doc, element):
    """ removes a specific node, adding its children in its place
    """
    fragment = doc.createDocumentFragment()
    while element.firstChild:
        fragment.appendChild(element.firstChild)

    parent = element.parentNode
    parent.insertBefore(fragment, element)
    parent.removeChild(element)

1
これは何語?
brunoais

Pythonのように見えます-ユーザーが言及しているので意味がありますpyjamas
mgilson 2015

0

重要なDOMに取り組みながら、パフォーマンスに関して最良の答えを探していました。

まぶたのない答えは、javascriptを使用するとパフォーマンスが最高になることを指摘していました。

削除するセクション内の複雑なDOM構成で、5,000行と400,000文字に対して次の実行時間テストを行いました。私は、JavaScriptを使用する際の便利な理由で、クラスの代わりにIDを使用しています。

$ .unwrap()の使用

$('#remove-just-this').contents().unwrap();

201.237ms

$ .replaceWith()の使用

var cnt = $("#remove-just-this").contents();
$("#remove-just-this").replaceWith(cnt);

156.983ms

JavaScriptでのDocumentFragmentの使用

var element = document.getElementById('remove-just-this');
var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

147.211ms

結論

パフォーマンスに関しては、比較的大きなDOM構造であっても、jQueryとjavascriptの使用の違いはそれほど大きくありません。驚くべきことに$.unwrap()、よりも高価です$.replaceWith()。テストはjQuery 1.12.4で行われました。


0

複数の行を処理している場合は、私のユースケースのように、おそらくこれらの行に沿って何かをしたほうがよいでしょう。

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.