Удалить все дочерние элементы узла 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);
}
Я видел, как люди делают:
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
метод.