¿Cómo eliminar solo el elemento principal y no sus elementos secundarios en JavaScript?


88

Digamos:

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

a esto:

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

He estado descubriendo el uso de Mootools, jQuery e incluso JavaScript (sin formato), pero no podía tener la idea de cómo hacerlo.

Respuestas:


138

Usando jQuery puedes hacer esto:

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

Enlaces rápidos a la documentación:


Ojalá me diera cuenta (err ... encontré ) esto hace 3 horas ... simple y elegante, ¡increíble!
Tathagata

3
¿Cuál es el significado de 'cnt'?
Steven Lu

1
'cnt' es solo un nombre de variable que contiene "contenido"
George Anderson

1
No estoy seguro de por qué, pero esto no funcionó para mí cuando usé contenido (). Sin embargo, cuando usé html () en lugar de contents (), ¡funcionó de maravilla!
vertigoelectric

versión de solo 1 línea:$('.remove-just-this').replaceWith(function() { return $(this).html(); });
Taufik Nur Rahmanda

36

El método independiente de la biblioteca consiste en insertar todos los nodos secundarios del elemento que se eliminará antes que él mismo (lo que los elimina implícitamente de su posición anterior), antes de eliminarlo:

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

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

Esto moverá todos los nodos secundarios al lugar correcto en el orden correcto.


3
JS moderno admite esto:node.replaceWith(...node.childNodes);
Gibolt

34

Debe asegurarse de hacer esto con el DOM, no innerHTML(y si usa la solución jQuery proporcionada por jk, asegúrese de que mueva los nodos DOM en lugar de usarlos innerHTMLinternamente), para preservar cosas como los controladores de eventos.

Mi respuesta es muy parecida a la de insin, pero funcionará mejor para estructuras grandes (agregar cada nodo por separado puede ser gravoso en los redibujos donde CSS debe volver a aplicarse para cada uno appendChild; con a DocumentFragment, esto solo ocurre una vez, ya que no se hace visible hasta después de su los niños se adjuntan y se agregan al documento).

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

Gracias; corto y directo.
brunoais


22

Una forma más elegante es

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

2
La mejor respuesta. Gracias.
user706420

7

¡Utilice JS moderno!

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

oldNode.replaceWith(newNode) es válido ES5

...array es el operador de propagación, pasando cada elemento de la matriz como parámetro


2

Cualquiera que sea la biblioteca que esté utilizando, debe clonar el div interno antes de eliminar el div externo del DOM. Luego, debe agregar el div interno clonado al lugar en el DOM donde estaba el div externo. Entonces los pasos son:

  1. Guarde una referencia al padre del div externo en una variable
  2. Copie el div interno a otra variable. Esto se puede hacer de una manera rápida y sucia guardando elinnerHTML div interno en una variable o puede copiar el árbol interno recursivamente nodo por nodo.
  3. Llame removeChildal padre del div externo con el div externo como argumento.
  4. Inserte el contenido interno copiado al padre del div externo en la posición correcta.

Algunas bibliotecas harán algo o todo esto por usted, pero algo como lo anterior estará sucediendo bajo el capó.



1

Reemplaza div con su contenido:

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

Si desea hacer lo mismo en pijama, así es como se hace. funciona muy bien (gracias a los párpados). Gracias a esto, he podido crear un editor de texto enriquecido adecuado que hace estilos correctamente sin estropear.

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
¿Que idioma es este?
brunoais

Parece python, lo que tiene sentido ya que el usuario lo menciona pyjamas.
mgilson

0

Estaba buscando la mejor respuesta en términos de rendimiento mientras trabajaba en un DOM importante.

La respuesta de eyelidlessness fue señalar que con javascript el rendimiento sería el mejor.

Hice las siguientes pruebas de tiempo de ejecución en 5,000 líneas y 400,000 caracteres con una composición DOM compleja dentro de la sección para eliminar. Estoy usando una ID en lugar de una clase por una razón conveniente cuando uso javascript.

Usando $ .unwrap ()

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

201.237ms

Usando $ .replaceWith ()

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

156,983 ms

Usando DocumentFragment en 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

Conclusión

En cuanto al rendimiento, incluso en una estructura DOM relativamente grande, la diferencia entre usar jQuery y javascript no es enorme. Sorprendentemente $.unwrap()es más costoso que $.replaceWith(). Las pruebas se han realizado con jQuery 1.12.4.


0

Si está tratando con varias filas, como fue en mi caso de uso, probablemente sea mejor con algo como esto:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.