Удалите все дочерние элементы 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();