Как удалить только родительский элемент, а не его дочерние элементы в JavaScript?


допустим:

<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 и даже (raw) JavaScript, но не мог понять, как это сделать.

11 79

11 ответов:

С помощью jQuery можно сделать так:

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

быстрые ссылки на документацию:

независимый от библиотеки метод должен вставить все дочерние узлы элемента, который будет удален перед собой (что неявно удаляет их из их старой позиции), прежде чем удалить его:

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

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

это переместит все дочерние узлы в правильное место в правильном порядке.

вы должны убедиться, что сделать это с DOM, а не innerHTML (и при использовании решения jQuery, предоставленного jk, убедитесь, что он перемещает узлы DOM, а не использует innerHTML внутренне), чтобы сохранить вещи, как обработчики событий.

мой ответ очень похож на insin, но будет лучше работать для больших структур (добавление каждого узла отдельно может облагаться налогом на перерисовки, где CSS должен быть повторно применен для каждого appendChild; С DocumentFragment, это происходит только один раз, так как это не сделано видимым до тех пор, пока все его дочерние элементы не будут добавлены и добавлены в документ).

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

более элегантный способ-это

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

используйте современные 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 - это оператор spread, передающий каждый элемент массива в качестве параметра

какую бы библиотеку вы ни использовали, вам нужно клонировать внутренний div перед удалением внешнего div из DOM. Затем вы должны добавить клонированный внутренний div в место в DOM, где был внешний div. Итак, шаги:

  1. Сохраните ссылку на внешний родитель div в переменной
  2. скопируйте внутренний div в другую переменную. Это можно сделать быстро и грязно, сохранив innerHTML из внутреннего div в переменную или вы можете скопировать внутреннее дерево рекурсивно узел за узлом.
  3. вызов removeChild на родителе внешнего div с внешним div в качестве аргумента.
  4. вставьте скопированное внутреннее содержимое в родительский элемент внешнего div в правильном положении.

некоторые библиотеки будут делать некоторые или все это для вас, но что-то вроде выше будет происходить под капотом.

и, так как вы пробовали в mootools, а вот решение в mootools.

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

обратите внимание, что это совершенно непроверено, но я работал с mootools раньше, и он должен работать.

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

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

Если вы хотите сделать то же самое в пижаме, вот как это делается. он отлично работает (спасибо за веки). благодаря этому я смог сделать правильный текстовый редактор, который правильно делает стили, не испортив их.

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)

Я искал лучший ответ производительность-мудрый во время работы над важным DOM.

ответ eyelidlessness указывал на то, что с помощью javascript выступления будут лучшими.

Я сделал следующие тесты времени выполнения на 5 000 строк и 400 000 символов с композицией complexe DOM внутри раздела для удаления. Я использую идентификатор вместо класса по удобной причине при использовании javascript.

используя $.разверните ()

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

201.237 ms

С помощью $.replaceWith()

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

156.983 ms

использование DocumentFragment в 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 МС

вывод

С точки зрения производительности, даже на относительно большой структуре DOM, разница между использованием jQuery и javascript не является огромный. Удивительно $.unwrap() это дороже, чем $.replaceWith(). Тесты были выполнены с помощью jQuery 1.12.4.

Если вы имеете дело с несколькими строками, как это было в моем случае вы, вероятно, лучше с чем-то вдоль этих линий:

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