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

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

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

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

и я хватаю узел, который я хочу так:

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

как я мог удалить детей foo Так что просто <p id="foo"></p> осталось?

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

myNode.childNodes = new Array();

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

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

25 ответов


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

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

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

var myNode = document.getElementById("foo");
while (myNode.firstChild) {
    myNode.removeChild(myNode.firstChild);
}

в настоящее время принятый ответ неверен о том, что 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 (все еще медленнее, чем предыдущие два) - удаление диапазона, но диапазоны не поддерживаются до 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 не работает)

"per-test-loop" Jsperf часто понимается как "per-iteration", и только первая итерация имеет узлы для удаления, поэтому результаты бессмысленны, во время публикации были неправильно настроены тесты в этом потоке.


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 методы удаления детей, что данные останутся.


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

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

Если вы не:

var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);

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

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

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


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

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

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

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

Поддержка Браузеров - 91% Апр 2018


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

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

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


element.textContent = '';

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


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

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();
}

есть несколько вариантов для достижения этого:

самый быстрый ():

while (node.lastChild) {
  node.removeChild(node.lastChild);
}

альтернативы (медленнее):

while (node.firstChild) {
  node.removeChild(node.firstChild);
}

while (node.hasChildNodes()) {
  node.removeChild(node.lastChild);
}

Benchmark с предлагаемыми вариантами


Я видел, как люди делают:

while (el.firstNode) {
    el.removeChild(el.firstNode);
}

потом кто-то сказал, используя el.lastNode быстрее

однако я бы подумал, что это самый быстрый:

var children = el.childNodes;
for (var i=children.length - 1; i>-1; i--) {
    el.removeNode(children[i]);
}

что вы думаете?

ps: эта тема спасла мне жизнь. мой аддон firefox был отклонен, потому что я использовал innerHTML. Это уже давно вошло в привычку. тогда я foudn этого. и я действительно заметил разницу в скорости. при загрузке innerhtml потребовалось некоторое время для обновления, однако по addElement его моментально!


var empty_element = function (element) {

    var node = element;

    while (element.hasChildNodes()) {              // selected elem has children

        if (node.hasChildNodes()) {                // current node has children
            node = node.lastChild;                 // set current node to child
        }
        else {                                     // last child found
            console.log(node.nodeName);
            node = node.parentNode;                // set node to parent
            node.removeChild(node.lastChild);      // remove last node
        }
    }
}

это удалит все узлы внутри элемента.


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

// @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, которые возвращают null при попытке доступа к 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 );

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


innerText является победителем! http://jsperf.com/innerhtml-vs-removechild/133. Во всех предыдущих тестах внутренний dom родительского узла удалялся на первой итерации, а затем innerHTML или removeChild, где применялся к пустому div.


самый простой способ удаления дочерних узлов узла через Javascript

var myNode = document.getElementById("foo");
while(myNode.hasChildNodes())
{
   myNode.removeChild(myNode.lastChild);
}

Как правило, JavaScript использует массивы для ссылок на списки узлов DOM. Таким образом, это будет работать хорошо, если у вас есть интерес к этому через массив HTMLElements. Кроме того, стоит отметить, потому что я использую ссылку на массив вместо JavaScript proto, это должно работать в любом браузере, включая IE.

while(nodeArray.length !== 0) {
  nodeArray[0].parentNode.removeChild(nodeArray[0]);
}

почему мы не следуем простейшему методу здесь "удалить" зацикленный внутри while.

const foo = document.querySelector(".foo");
while (foo.firstChild) {
  foo.firstChild.remove();     
}
  • выбор родительского div
  • использование метода "remove"внутри цикла While для устранения первого дочернего элемента , пока не останется ни одного.

самый простой способ:

let container = document.getElementById("containerId");
container.innerHTML = "";

простое и быстрое использование для цикла!!

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

    for(var i = myNode.childNodes.length - 1; i >= 0; --i) {
      myNode.removeChild(myNode.childNodes[i]);
    }

это не будет работать в <span> тег!


вот что я обычно делаю :

HTMLElement.prototype.empty = function() {
    while (this.firstChild) {
        this.removeChild(this.firstChild);
    }
}

и вуаля, позже вы можете очистить любой элемент DOM с :

anyDom.empty()

другие способы в jQuery

var foo = $("#foo");
foo.children().remove();
or
$("*", foo ).remove();
or
foo.html("");

просто только IE:

parentElement.removeNode(true);

true - означает сделать глубокое удаление-это означает, что все дети также удаляются


это чистый javascript, который я использую не jQuery, но работает во всех браузерах, даже IE

<div id="my_div">
 <p>i am the first child</p>
 <p>i am another paragraphs</p>
 <p>enven me also i am another paragraphs</p>
</div>
<button id ="my_button>Remove nodes ?</button>

document.getElementById("my_button").addEventListener("click",function(){

  let parent_node =document.getElemetById("my_div");
  let last_child  =parent_node.lastChild;
  while(last_child){
    parent_node.removeChild(last_child);
  }
})

или вы можете симпли этого

document.getElementById("my_button").addEventListener("click",function(){

 let parent_node =document.getElemetById("my_div");
 parent_node.innerHTML ="";

})

если вы хотите положить что-то обратно в это div на innerHTML наверное лучше.

мой пример:

<ul><div id="result"></div></ul>

<script>
  function displayHTML(result){
    var movieLink = document.createElement("li");
    var t = document.createTextNode(result.Title);
    movieLink.appendChild(t);
    outputDiv.appendChild(movieLink);
  }
</script>

если я использую .firstChild или .lastChild метод displayHTML() функция не работает после этого, но никаких проблем с .innerHTML метод.


С помощью jQuery :

$("#foo").find("*").remove();