Wie entferne ich nur das übergeordnete Element und nicht die untergeordneten Elemente in JavaScript?

88

Sagen wir:

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

dazu:

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

Ich habe es mit Mootools, jQuery und sogar (rohem) JavaScript herausgefunden, konnte aber nicht auf die Idee kommen, wie das geht.

cheeaun
quelle

Antworten:

138

Mit jQuery können Sie Folgendes tun:

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

Schnelle Links zur Dokumentation:

jk.
quelle
Ich wünschte, ich hätte das vor 3 Stunden realisiert (äh ... gefunden ) ... einfach und elegant - großartig!
Tathagata
3
Welche Bedeutung hat 'cnt'?
Steven Lu
1
'cnt' ist nur ein Variablenname, der "Inhalt" enthält
George Anderson
1
Ich bin mir nicht sicher warum, aber das hat bei der Verwendung von content () nicht funktioniert. Als ich jedoch html () anstelle von content () verwendete, funktionierte es wie ein Zauber!
schwindelerregende
nur 1 Zeile Version:$('.remove-just-this').replaceWith(function() { return $(this).html(); });
Taufik Nur Rahmanda
36

Die bibliotheksunabhängige Methode besteht darin, alle untergeordneten Knoten des zu entfernenden Elements vor sich selbst einzufügen (wodurch sie implizit von ihrer alten Position entfernt werden), bevor Sie es entfernen:

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

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

Dadurch werden alle untergeordneten Knoten in der richtigen Reihenfolge an die richtige Stelle verschoben.

Jonny Buchanan
quelle
3
Modern JS unterstützt dies:node.replaceWith(...node.childNodes);
Gibolt
34

Sie sollten sicherstellen, dass Sie dies nicht mit dem DOM tun innerHTML(und wenn Sie die von jk bereitgestellte jQuery-Lösung verwenden, stellen Sie sicher, dass die DOM-Knoten verschoben werden, anstatt sie innerHTMLintern zu verwenden), um Dinge wie Ereignishandler beizubehalten.

Meine Antwort ähnelt der von insin, ist jedoch für große Strukturen besser geeignet (das Anhängen jedes Knotens kann eine Belastung für Neuzeichnungen darstellen, bei denen CSS für jeden erneut angewendet werden muss appendChild; mit a DocumentFragmenttritt dies nur einmal auf, da es erst nach seiner Darstellung sichtbar gemacht wird Kinder werden alle angehängt und dem Dokument hinzugefügt.

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);
Augenlidlosigkeit
quelle
Danke dir; kurz und direkt.
Brunoais
28
 $('.remove-just-this > *').unwrap()
campino2k
quelle
22

Eleganter ist der Weg

$('.remove-just-this').contents().unwrap();
Yunda
quelle
2
Beste Antwort. Vielen Dank.
user706420
7

Verwenden Sie moderne 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) ist gültig ES5

...array ist der Spread-Operator, der jedes Array-Element als Parameter übergibt

Gibolt
quelle
2

Unabhängig davon, welche Bibliothek Sie verwenden, müssen Sie das innere Div klonen, bevor Sie das äußere Div aus dem DOM entfernen. Dann müssen Sie das geklonte innere Div an der Stelle im DOM hinzufügen, an der sich das äußere Div befand. Die Schritte sind also:

  1. Speichern Sie einen Verweis auf das übergeordnete Element des äußeren Div in einer Variablen
  2. Kopieren Sie das innere Div in eine andere Variable. Dies kann schnell und schmutzig erfolgen, indem Sie das speicherninnerHTML das innere Div in einer Variablen gespeichert wird, oder Sie können den inneren Baum Knoten für Knoten rekursiv kopieren.
  3. Rufen Sie removeChilddas Elternteil des äußeren Div mit dem äußeren Div als Argument auf.
  4. Fügen Sie den kopierten inneren Inhalt an der richtigen Position in das übergeordnete Element des äußeren Div ein.

Einige Bibliotheken erledigen dies ganz oder teilweise für Sie, aber so etwas wird unter der Haube passieren.

domgblackwell
quelle
1

Ersetzen Sie div durch seinen Inhalt:

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>

Johannes Buchholz
quelle
0

Wenn Sie dasselbe im Pyjama machen möchten, gehen Sie wie folgt vor. es funktioniert super (danke an die Augenlider). Dank dessen konnte ich einen richtigen Rich-Text-Editor erstellen, der Stile richtig macht, ohne es zu vermasseln.

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)
user362834
quelle
1
Welche Sprache ist das?
Brunoais
Sieht aus wie Python - was Sinn macht, da der Benutzer erwähnt pyjamas.
mgilson
0

Ich suchte nach der besten Antwort in Bezug auf die Leistung, während ich an einem wichtigen DOM arbeitete.

Die Antwort von eyelidlessness war, darauf hinzuweisen, dass die Aufführungen mit Javascript am besten wären.

Ich habe die folgenden Ausführungszeittests für 5.000 Zeilen und 400.000 Zeichen mit einer komplexen DOM-Komposition innerhalb des zu entfernenden Abschnitts durchgeführt. Ich verwende aus praktischen Gründen eine ID anstelle einer Klasse, wenn ich Javascript verwende.

Verwenden von $ .unwrap ()

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

201,237 ms

Verwenden von $ .replaceWith ()

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

156,983 ms

Verwenden von DocumentFragment in Javascript

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

147,211 ms

Fazit

In Bezug auf die Leistung ist der Unterschied zwischen der Verwendung von jQuery und Javascript selbst bei einer relativ großen DOM-Struktur nicht groß. Überraschenderweise $.unwrap()ist am teuersten als $.replaceWith(). Die Tests wurden mit jQuery 1.12.4 durchgeführt.

maxime_039
quelle
0

Wenn Sie mit mehreren Zeilen arbeiten, wie es in meinem Anwendungsfall der Fall war, sind Sie wahrscheinlich mit etwas in dieser Richtung besser dran:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
Iso
quelle