it-swarm.com.de

Wie entferne ich nur das übergeordnete Element und nicht dessen untergeordnete Elemente in JavaScript?

Sagen wir:

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

zu diesem:

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

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

80
cheeaun

Mit jQuery können Sie Folgendes tun:

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

Schnelle Links zur Dokumentation:

127
jk.

Die bibliotheksunabhängige Methode besteht darin, alle untergeordneten Knoten des zu entfernenden Elements vor sich selbst einzufügen (wodurch sie implizit aus ihrer alten Position entfernt werden), bevor Sie sie 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.

35
Jonny Buchanan

Sie sollten dies mit dem DOM und nicht mit innerHTML tun (und wenn Sie die von jk bereitgestellte jQuery-Lösung verwenden, stellen Sie sicher, dass die DOM-Knoten verschoben werden, anstatt innerHTML intern zu verwenden), um beispielsweise Event-Handler zu erhalten.

Meine Antwort ist sehr ähnlich wie die von Insins, wird jedoch bei großen Strukturen besser funktionieren (das Anhängen jedes Knotens kann eine Neuanwendung erfordern, wenn CSS für jede appendChild erneut angewendet werden muss; bei einer DocumentFragment tritt dies nur einmal auf, da sie erst sichtbar wird nachdem alle untergeordneten Elemente angehängt wurden und sie dem Dokument hinzugefügt werden).

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);
32
eyelidlessness
 $('.remove-just-this > *').unwrap()
25
campino2k

Eleganter geht es

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

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

4
Gibolt

Und da Sie auch in mootools versucht haben, hier die Lösung in mootools.

var children = $('remove-just-this').getChildren();
children.replaces($('remove-just-this');

Beachten Sie, dass dies völlig ungetestet ist, aber ich habe bereits mit Mootools gearbeitet und es sollte funktionieren.

http://mootools.net/docs/Element/Element#Element:getChildren

http://mootools.net/docs/Element/Element#Element:replaces

2
tj111

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 die Stelle im DOM hinzufügen, an der das äußere Div war. Die Schritte sind also:

  1. Speichern Sie einen Verweis auf das übergeordnete div des übergeordneten div in einer Variablen
  2. Kopiere das innere div in eine andere Variable. Dies kann auf eine schnelle und schmutzige Weise durch Speichern der innerHTML des inneren div in einer Variablen erfolgen, oder Sie können den inneren Baum rekursiv Knoten für Knoten kopieren.
  3. Rufen Sie removeChild am übergeordneten Element des äußeren div mit dem äußeren div als Argument auf.
  4. Fügen Sie den kopierten inneren Inhalt an der übergeordneten Stelle des äußeren Div an der richtigen Stelle ein.

Einige Bibliotheken erledigen das alles für Sie, aber so etwas wird unter der Haube passieren.

2
domgblackwell

wenn Sie das Gleiche auch im Pyjama machen möchten, gehen Sie wie folgt vor. es funktioniert super (danke an augenlidness). Ich habe es geschafft, einen richtigen Rich Text-Editor zu erstellen, der Styles dank dieser Funktion ordnungsgemäß durchführt.

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)
0
user362834

Ich habe nach der besten Antwort gesucht performance-wise, während ich an einem wichtigen DOM arbeitete.

eyelidlessness antwortete darauf, dass mit javascript die leistungen am besten wären.

Ich habe die folgenden Ausführungstests mit 5.000 Zeilen und 400.000 Zeichen durchgeführt, wobei eine komplexe DOM-Komposition innerhalb des Abschnitts entfernt werden sollte. Bei der Verwendung von Javascript verwende ich aus praktischen Gründen eine ID anstelle einer Klasse.

Verwenden von $ .unwrap ()

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

201.237ms

$ .ReplaceWith () verwenden

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

156,983 ms

DocumentFragment in Javascript verwenden

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 puncto Leistung ist der Unterschied zwischen jQuery und Javascript selbst bei einer relativ großen DOM-Struktur nicht groß. Überraschenderweise ist $.unwrap() am teuersten als $.replaceWith(). Die Tests wurden mit jQuery 1.12.4 durchgeführt.

0
maxime_039

Ersetze div durch den 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>
0

Wenn Sie mit mehreren Zeilen zu tun haben, wie es in meinem Anwendungsfall der Fall war, ist es wahrscheinlich besser, wenn Sie etwas in der folgenden Richtung verwenden:

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