如何在JavaScript中删除DOM节点的所有子元素?

假设我有以下(丑陋的)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?

我希望答案是直接的DOM;不过,如果你在jQuery中提供了一个dom专用的答案,会有额外的加分。


当前回答

为什么我们不在这里使用最简单的方法“remove”循环在while中。

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

选择父div 在While循环中使用“remove”方法消除第一个子元素,直到没有剩余。

其他回答

刚刚看到有人在另一个问题中提到这个问题,我想我会添加一个我还没有看到的方法:

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

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

clear函数获取元素并使用父节点将其自身替换为没有其子节点的副本。如果元素是稀疏的,则性能增益不大,但当元素有一堆节点时,性能增益就实现了。

2022年+,用替代品!

现在可以使用(跨浏览器支持的)replaceChildren API替换所有的子程序:

container.replaceChildren(...arrayOfNewChildren);

这可以做到这两点:

删除所有现有的子节点,和 在一个操作中追加所有给定的新子节点。

你也可以使用相同的API来删除现有的子节点,而不替换它们:

container.replaceChildren();

这在Chrome/Edge 86+, Firefox 78+和Safari 14+中完全支持。它是完全指定的行为。这可能比这里提出的任何其他方法都要快,因为删除旧的子元素和添加新的子元素不需要innerHTML,而且是一步完成的,而不是多个步骤。

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方法删除子元素,那么这些数据将会保留。

你可以从一个容器中删除所有子元素,如下所示:

function emptyDom(selector){
 const elem = document.querySelector(selector);
 if(elem) elem.innerHTML = "";
}

现在你可以调用函数并像下面这样传递选择器:

如果元素id = foo

emptyDom('#foo');

如果元素有class = foo

emptyDom('.foo');

如果元素有tag = <div>

emptyDom('div')

元素。innerHTML = ""(或.textContent)是目前为止最快的解决方案

这里的大多数答案都是基于有缺陷的测试

例如: https://jsperf.com/innerhtml-vs-removechild/15 该测试不会在每次迭代之间向元素添加新的子元素。第一次迭代将删除元素的内容,然后每一次迭代都不执行任何操作。 在这种情况下,while (box. lastchild) box. removecchild (box. lastchild)更快,因为box. lastchild。lastChild在99%的情况下为null

这里有一个合适的测试:https://jsperf.com/innerhtml-conspiracy

最后,不要使用node. parentnode . replacechild (node. clonenode (false), node)。这将用节点本身的副本替换它的子节点。但是,这不会保留事件侦听器,并破坏对该节点的任何其他引用。