如何在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专用的答案,会有额外的加分。
我是这样做的
data = {
"messages": [
[0, "userName", "message test"],
[1, "userName1", "message test1"]
]
}
for (let i = 0; i < data.messages.length; i++) {
var messageData = document.createElement('span')
messageData.className = 'messageClass'
messageData.innerHTML = `${data.messages[i][2]} ${'<br />'}`
$(".messages").append(messageData)
}
$('#removeMessages').on('click', () => {
node = $('.messages').get(0)
while (node.firstChild) {
node.firstChild.remove()
}
$('#removeMessages').toggle(500)
$('#addMessages').toggle(500)
})
$('#addMessages').on('click', () => {
for (let i = 0; i < data.messages.length; i++) {
var messageData = document.createElement('span')
messageData.className = 'messageClass'
messageData.innerHTML = `${data.messages[i][2]} ${'<br />'}`
$(".messages").append(messageData)
}
$('#addMessages').toggle(500)
$('#removeMessages').toggle(500)
})
#addMessages{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="messages"></div>
<button type='button' id="removeMessages">Remove</button>
<button type='button' id="addMessages">Add MEssages</button>
目前公认的答案是错误的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/167 http://jsperf.com/innerhtml-vs-removechild/300
https://jsperf.com/remove-all-child-elements-of-a-dom-node-in-javascript
(重新启动jsperf的新url,因为编辑旧url不工作)
Jsperf的“per-test-loop”通常被理解为“per-iteration”,只有第一次迭代需要删除节点,所以结果是没有意义的,在发布的时候,这个线程中的测试设置不正确。