Удалить все дочерние элементы узла DOM в JavaScript - PullRequest
728 голосов
/ 18 октября 2010

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

Скажем, у меня есть следующий (безобразный) HTML:

<p id="foo">
    <span>hello</span>
    <div>world</div>
</p>

И я беру нужный мне узел так:

var myNode = document.getElementById("foo");

Как я могу удалить детей из foo, чтобы осталось только <p id="foo"></p>? 1011 *

Могу я просто сделать:

myNode.childNodes = new Array();

или я должен использовать какую-то комбинацию removeElement?

Я бы хотел, чтобы ответ был прямым DOM; хотя дополнительные баллы, если вы также предоставите ответ в jQuery вместе с ответом только для DOM.

Ответы [ 27 ]

1439 голосов
/ 18 октября 2010

Вариант 1 (намного медленнее, см. Комментарии ниже):

var myNode = document.getElementById("foo");
myNode.innerHTML = '';

Вариант 2 (намного быстрее):

var myNode = document.getElementById("foo");
while (myNode.firstChild) {
    myNode.removeChild(myNode.firstChild);
}
94 голосов
/ 09 апреля 2014

В настоящее время принят неправильный ответ о том, что innerHTML медленнее (по крайней мере, в IE и Chrome), как правильно заметил m93a.

Chrome и FF значительно быстрее, используя этот метод (который уничтожит прикрепленные данные jquery):

var cNode = node.cloneNode(false);
node.parentNode.replaceChild(cNode, node);

в отдаленную секунду для FF и Chrome и самый быстрый в IE:

node.innerHTML = '';

InnerHTML не разрушит ваши обработчики событий и не нарушит ссылки на jquery , это также рекомендуется в качестве решения здесь: https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML.

Самый быстрый метод манипулирования DOM (все еще медленнее, чем предыдущие два) - это удаление Range, но диапазоны не поддерживаются до IE9.

var range = document.createRange();
range.selectNodeContents(node);
range.deleteContents();

Другие упомянутые методы кажутся сопоставимыми, но намного медленнее, чем innerHTML, за исключением выброса, jquery (1.1.1 и 3.1.1), который значительно медленнее, чем что-либо еще:

$(node).empty();

Доказательства здесь:

http://jsperf.com/innerhtml-vs-removechild/167 http://jsperf.com/innerhtml-vs-removechild/300 https://jsperf.com/remove-all-child-elements-of-a-dom-node-in-javascript (Новый URL для перезагрузки jsperf, потому что редактирование старого URL не работает)

«Цикл на тест» Jsperf часто понимается как «на каждую итерацию», и только у первой итерации есть узлы для удаления, поэтому результаты не имеют смысла, на момент публикации в этом потоке были неправильно настроены тесты.

41 голосов
/ 18 октября 2010
var myNode = document.getElementById("foo");
var fc = myNode.firstChild;

while( fc ) {
    myNode.removeChild( fc );
    fc = myNode.firstChild;
}

Если есть вероятность, что у вас есть потомки, затронутые jQuery, тогда вы должны использовать какой-то метод, который очистит данные jQuery.

$('#foo').empty();

Метод jQuery .empty() обеспечит очистку любых данных, связанных с удаляемыми элементами jQuery.

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

35 голосов
/ 15 ноября 2016

Используйте современный Javascript с remove!

const parent = document.getElementById("foo");
while (parent.firstChild) {
    parent.firstChild.remove();
}

Это более новый способ записи удаления узлов в ES5.Это ванильный JS и читает намного лучше, чем предыдущие версии.

У большинства пользователей должны быть современные браузеры, или вы можете перейти вниз, если это необходимо.

Поддержка браузера - 94% май 2019

34 голосов
/ 18 октября 2010

Если вы используете jQuery:

$('#foo').empty();

Если вы не используете:

var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);
19 голосов
/ 02 апреля 2013

Самый быстрый ...

var removeChilds = function (node) {
    var last;
    while (last = node.lastChild) node.removeChild(last);
};

Спасибо Андрею Лушникову за его ссылку на jsperf.com (классный сайт!).

РЕДАКТИРОВАТЬ: для ясности, в Chrome нет разницы в производительности между firstChild и lastChild. Верхний ответ показывает хорошее решение для производительности.

9 голосов
/ 18 октября 2010

Если вы хотите иметь только узел без дочерних узлов, вы также можете сделать его копию следующим образом:

var dupNode = document.getElementById("foo").cloneNode(false);

Зависит от того, чего вы пытаетесь достичь.

6 голосов
/ 28 марта 2014
element.textContent = '';

Это как innerText, кроме стандартного. Это немного медленнее , чем removeChild(), но его проще использовать и не будет сильно влиять на производительность, если у вас не будет слишком много материала для удаления.

5 голосов
/ 12 марта 2014

Вот еще один подход:

function removeAllChildren(theParent){

    // Create the Range object
    var rangeObj = new Range();

    // Select all of theParent's children
    rangeObj.selectNodeContents(theParent);

    // Delete everything that is selected
    rangeObj.deleteContents();
}
4 голосов
/ 16 марта 2013

В ответ на ДанМана, Мартена и Мэтта.Клонирование узла для установки текста действительно является жизнеспособным способом в моих результатах.

// @param {node} node
// @return {node} empty node
function removeAllChildrenFromNode (node) {
  var shell;
  // do not copy the contents
  shell = node.cloneNode(false);

  if (node.parentNode) {
    node.parentNode.replaceChild(shell, node);
  }

  return shell;
}

// use as such
var myNode = document.getElementById('foo');
myNode = removeAllChildrenFromNode( myNode );

Также это работает для узлов, не входящих в dom, которые возвращают ноль при попытке доступа к parentNode.Кроме того, если вам нужно быть в безопасности, перед добавлением контента узел пуст, это действительно полезно.Рассмотрим вариант использования ниже.

// @param {node} node
// @param {string|html} content
// @return {node} node with content only
function refreshContent (node, content) {
  var shell;
  // do not copy the contents
  shell = node.cloneNode(false);

  // use innerHTML or you preffered method
  // depending on what you need
  shell.innerHTML( content );

  if (node.parentNode) {
    node.parentNode.replaceChild(shell, node);
  }

  return shell;
}

// use as such
var myNode = document.getElementById('foo');
myNode = refreshContent( myNode );

Я считаю этот метод очень полезным при замене строки внутри элемента, если вы не уверены, что будет содержать узел, вместо того, чтобы беспокоиться о том, как убрать беспорядокначать все заново.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...