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

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

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

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

И я хватаю node Я хочу так:

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

Как удалить дочерние элементы foo, чтобы оставить только <p id="foo"></p>?

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

myNode.childNodes = new Array();

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

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

Ответ 1

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

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  myNode.innerHTML = '';
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove Via innerHTML</button>

Ответ 2

В настоящее время принят неправильный ответ о том, что 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 "per-test-loop" часто понимается как "per-iteration", и только в первой итерации есть узлы для удаления, поэтому результаты не имеют смысла, на момент публикации в этом потоке были неправильно настроены тесты.

Ответ 3

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

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

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

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

Метод jQuery .empty() гарантирует, что все данные, связанные с удалением элементов jQuery, будут очищены.

Если вы просто используете методы t12 > удаления детей, эти данные будут оставаться.

Ответ 4

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

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

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

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

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

Ответ 5

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

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

Если вы этого не сделаете:

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

Ответ 6

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

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

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

ОБНОВЛЕНИЕ: чтобы быть ясным, нет никакой разницы в производительности в Chrome между firstChild и lastChild. Верхний ответ показывает хорошее решение для производительности.

Ответ 7

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

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

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

Ответ 8

element.textContent = '';

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

Ответ 9

Здесь другой подход:

function removeAllChildren(theParent){

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

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

    // Delete everything that is selected
    rangeObj.deleteContents();
}

Ответ 10

В ответ на DanMan, Maarten и Matt. Клонирование 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. Кроме того, если вам нужно быть в безопасности, node пуст, прежде чем добавлять контент, это действительно полезно. Рассмотрим пример использования ниже.

// @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 );

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

Ответ 11

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
        }
    }
}

Это приведет к удалению всех узлов внутри элемента.

Ответ 12

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

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

как вы думаете?

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

Ответ 13

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

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

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

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

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

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

Контрольная точка с предлагаемыми опциями

Ответ 14

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

Ответ 15

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

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

Ответ 16

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

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

И voila, позже вы можете удалить любой элемент dom с помощью:

anyDom.empty()

Ответ 17

Использование диапазона диапазона чувствует себя наиболее естественным для меня:

for (var child of node.childNodes) {
    child.remove();
}

Согласно моим измерениям в Chrome и Firefox, он примерно на 1,3 раза медленнее. В нормальных обстоятельствах это, возможно, не имеет значения.

Ответ 18

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

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

Ответ 19

Почему мы не следуем простейшему методу, здесь "удаляем" внутри внутри.

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

Ответ 20

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

$("#target").empty(); 

пример кода:

$("#button").click(function(){
    $("#target").empty();
});

Ответ 21

Просто увидел, что кто-то упоминает этот вопрос в другом, и думал, что добавлю метод, который я еще не видел:

function clear(el) {
    el.parentNode.replaceChild(el.cloneNode(false), el);
}

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

Функция clear выполняет элемент и использует родительский узел, чтобы заменить его копией без нее. Не так много прироста производительности, если элемент разрежен, но когда элемент имеет кучу узлов, реализуется производительность.

Ответ 22

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

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

Ответ 23

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

parentElement.removeNode(true);

true - означает глубокое удаление - это означает, что все дочерние элементы также удалены

Ответ 24

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

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

Ответ 25

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

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

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

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

Ответ 26

Вариант 2 из выигрышного ответа.

function emptyElement(element) {
      var myNode = element;
      while (myNode.firstChild) {
          myNode.removeChild(myNode.firstChild);
      }
    }

   emptyElement(document.body)

Ответ 27

Если вы хотите вернуть что-то в это 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.

Ответ 28

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

   <div id="my_div">
    <p>Paragraph one</p>
    <p>Paragraph two</p>
    <p>Paragraph three</p>
   </div>
   <button id ="my_button>Remove nodes ?</button>

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

  let parent_node =document.getElemetById("my_div"); //Div which contains paagraphs

  //Let find numbers of child inside the div then remove all
  for(var i =0; i < parent_node.childNodes.length; i++) {
     //To avoid a problem which may happen if there is no childNodes[i] 
     try{
       if(parent_node.childNodes[i]){
         parent_node.removeChild(parent_node.childNodes[i]);
       }
     }catch(e){
     }
  }

})

or you may simpli do this which is a quick way to do

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

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

})

Ответ 29

с jQuery:

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