Удалить все дочерние элементы узла 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-only.
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/167http://jsperf.com/innerhtml-vs-removechild/300https://jsperf.com/remove-all-child-elements-of-a-dom-node-in-javascript (Новый url для перезагрузки jsperf, потому что редактирование старого url не работает)Jsperf "за цикл тестирования " часто понимается как" за итерацию", и только первая итерация имеет узлы для удаления, поэтому результаты бессмысленны, во время постинга были неправильно настроены тесты в этой теме.
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% Apr 2018
Если вы только хотите иметь узел без его дочерних элементов, вы также можете сделать его копию следующим образом:
var dupNode = document.getElementById("foo").cloneNode(false);зависит от того, что вы пытаетесь достичь.
element.textContent = '';это как внутренний текст, кроме стандартного. Это немного медленнее чем
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. Это уже давно вошло в привычку. тогда я понял это. и я действительно заметил разницу в скорости. при загрузке 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 } } }это приведет к удалению всех узлов в элементе.
в ответ на DanMan, Маартен и Мэтт. Клонирование узла, чтобы установить текст, действительно является жизнеспособным способом в моих результатах.
// @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]); }
почему мы не следуем простейшему методу здесь "удалить" петлю внутри в то время как.
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метод.
Comments