如何在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专用的答案,会有额外的加分。


当前回答

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

其他回答

Ecma6使它简单而紧凑

myNode.querySelectorAll('*').forEach( n => n.remove() );

这回答了问题,并删除了“所有子节点”。

如果有属于myNode的文本节点,它们不能被CSS选择器选中,在这种情况下,我们必须应用(also):

myNode.textContent = '';

实际上,最后一个可能是最快和更有效的解决方案。

.textContent比.innerText和.innerHTML更有效,参见:MDN

有几个选项可以实现这一目标:

最快的():

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

选择(慢):

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

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

使用建议的选项进行基准测试

jQuery的其他方法

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

元素。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)。这将用节点本身的副本替换它的子节点。但是,这不会保留事件侦听器,并破坏对该节点的任何其他引用。

简单的只有IE:

parentElement.removeNode(true);

True -意味着做深层移除-这意味着所有的子也被移除