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


当前回答

使用elm.replaceChildren()。

它是实验性的,没有广泛的支持,但当不带参数执行时,它会做你所要求的,而且它比遍历每个子节点并删除它更有效。如前所述,用空字符串替换innerHTML将需要浏览器进行HTML解析。

MDN文档

它现在得到了广泛的支持

其他回答

选项1 A:清除innerHTML。

这种方法很简单,但可能不适合高性能应用程序,因为它调用浏览器的HTML解析器(尽管浏览器可能针对值为空字符串的情况进行优化)。

doFoo。Onclick = () => { const myNode = document.getElementById("foo"); myNode。innerHTML = "; } <div id='foo' style="height: 100px;宽度:100 px;边框:1px纯黑色;" > < span >你好> < /跨度 < / div > <button id='doFoo'>通过innerHTML删除</button>

选项1 B:清除文本内容

如上所述,但是使用. textcontent。根据MDN,这将比innerHTML更快,因为浏览器不会调用他们的HTML解析器,而是立即用单个#text节点替换元素的所有子元素。

doFoo。Onclick = () => { const myNode = document.getElementById("foo"); myNode。textContent = "; } <div id='foo' style="height: 100px;宽度:100 px;边框:1px纯黑色;" > < span >你好> < /跨度 < / div > <按钮id='doFoo'>删除通过textContent</按钮>

选项2 A:循环删除每个lastChild:

这个答案的早期编辑使用了firstChild,但在计算机科学中更新为使用lastChild,一般来说,删除集合的最后一个元素比删除第一个元素要快得多(这取决于集合是如何实现的)。 循环继续检查firstChild,以防检查firstChild比检查lastChild快(例如,如果元素列表被UA实现为有向链表)。

doFoo。Onclick = () => { const myNode = document.getElementById("foo"); while (myNode.firstChild) { myNode.removeChild (myNode.lastChild); } } <div id='foo' style="height: 100px;宽度:100 px;边框:1px纯黑色;" > < span >你好> < /跨度 < / div > <button id='doFoo'>通过lastChild-loop删除</button>

选项2 B:循环删除每个lastElementChild:

这种方法保留了所有非element(即#text节点和<!)——comments——>)父类的子类(但不是它们的后代)——这可能在你的应用程序中是可取的(例如,一些模板系统使用内联HTML注释来存储模板指令)。 这种方法直到最近几年才被使用,因为Internet Explorer只在IE9中添加了对lastElementChild的支持。

doFoo。Onclick = () => { const myNode = document.getElementById("foo"); while (myNode.lastElementChild) { myNode.removeChild (myNode.lastElementChild); } } <div id='foo' style="height: 100px;宽度:100 px;边框:1px纯黑色;" > <!——这条评论不会被删除——> < span > <你好!-></span> . -></span> . - <!——但这只不会。--> < / div > <button id='doFoo'>通过lastElementChild-loop删除</button>

好处:元素。clearChildren monkey-patch:

我们可以在JavaScript中的Element原型中添加一个新的method-property,以简化对它的调用,只调用el. clearchildren()(其中el是任何HTML元素对象)。 (严格地说,这是一个猴子补丁,而不是一个polyfill,因为这不是一个标准的DOM特性或缺失的特性。请注意,在许多情况下,不鼓励打猴子补丁。)

if( typeof Element.prototype.clearChildren === 'undefined' ) { Object.defineProperty(Element.prototype, 'clearChildren', { configurable: true, enumerable: false, value: function() { while(this.firstChild) this.removeChild(this.lastChild); } }); } <div id='foo' style="height: 100px; width: 100px; border: 1px solid black;"> <span>Hello <!-- This comment WILL be removed --></span> </div> <button onclick="this.previousElementSibling.clearChildren()">Remove via monkey-patch</button>

使用range循环对我来说是最自然的:

for (var child of node.childNodes) {
    child.remove();
}

根据我在Chrome和Firefox中的测量,它要慢1.3倍左右。在正常情况下,这或许无关紧要。

最快的…

var removeChilds = function (node) {
    var last;
    while (last = node.lastChild) node.removeChild(last);
};

感谢Andrey Lushnikov提供的jsperf.com链接(很酷的网站!)

编辑:需要明确的是,在Chrome中,firstChild和lastChild之间没有性能差异。上面的答案显示了一个很好的性能解决方案。

迭代地从DOM中删除节点的所有子节点的一行程序

Array.from(node.children).forEach(c => c.remove())

Or

[...node.children].forEach(c => c.remove())

通过Javascript删除节点的子节点的最简单方法

var myNode = document.getElementById("foo");
while(myNode.hasChildNodes())
{
   myNode.removeChild(myNode.lastChild);
}