如何在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的答案,那么可以提供额外的分数。
答案 0 :(得分:1396)
选项1(慢得多,见下面的评论):
var myNode = document.getElementById("foo");
myNode.innerHTML = '';
选项2(快得多):
var myNode = document.getElementById("foo");
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
答案 1 :(得分:90)
目前接受的答案是错误的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
(jsperf重启的新url,因为编辑旧的url不起作用)
Jsperf的“per-test-loop”通常被理解为“per-iteration”,并且只有第一次迭代才有删除的节点,因此结果毫无意义,在发布时,此线程中的测试设置不正确。
答案 2 :(得分:43)
replaceChildren()
API!现在可以使用(支持跨浏览器)replaceChildren() API 来替换所有子项:
container.replaceChildren(...arrayOfNewChildren);
这将同时执行以下两项操作:a) 删除所有现有子项,以及 b) 在一次操作中附加所有给定的新子项。
您也可以使用相同的 API 来删除现有的子项,而不替换它们:
container.replaceChildren();
Chrome/Edge 86+、Firefox 78+ 和 Safari 14+ 完全支持此功能。(请注意,目前 Safari 的 MDN 数据不正确。)fully specified行为。这可能比这里任何其他建议的方法更快,因为移除旧子节点和添加新子节点 a) 不需要 innerHTML
,并且 b) 一步完成多个。
答案 3 :(得分:41)
var myNode = document.getElementById("foo");
var fc = myNode.firstChild;
while( fc ) {
myNode.removeChild( fc );
fc = myNode.firstChild;
}
如果你有任何机会让jQuery受影响的后代,那么你必须使用一些清理jQuery数据的方法。
$('#foo').empty();
The jQuery .empty()
method将确保清除与要删除的元素相关联的jQuery的任何数据。
如果您只是使用DOM
方法删除子项,则该数据将保留。
答案 4 :(得分:34)
如果你使用jQuery:
$('#foo').empty();
如果你不这样做:
var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);
答案 5 :(得分:33)
remove
!const parent = document.getElementById("foo");
while (parent.firstChild) {
parent.firstChild.remove();
}
这是在ES5中编写节点删除的更新方法。它是vanilla JS并且比以前的版本更好地读取 。
大多数用户应该使用现代浏览器,或者您可以根据需要进行细分。
Browser Support - 2014年5月94%
答案 6 :(得分:19)
最快......
var removeChilds = function (node) {
var last;
while (last = node.lastChild) node.removeChild(last);
};
感谢Andrey Lushnikov his link to jsperf.com(很酷的网站!)。
编辑:很明显,Chrome在firstChild和lastChild之间没有任何性能差异。最佳答案显示了良好的性能解决方案。
答案 7 :(得分:9)
如果您只想让节点没有子节点,您也可以像这样复制它:
var dupNode = document.getElementById("foo").cloneNode(false);
取决于你想要达到的目标。
答案 8 :(得分:6)
element.textContent = '';
它与innerText相似,但标准除外。它a bit slower比removeChild()
更快,但它更容易使用,如果你没有太多的东西,它将不会产生很大的性能差异删除。
答案 9 :(得分:5)
这是另一种方法:
function removeAllChildren(theParent){
// Create the Range object
var rangeObj = new Range();
// Select all of theParent's children
rangeObj.selectNodeContents(theParent);
// Delete everything that is selected
rangeObj.deleteContents();
}
答案 10 :(得分:4)
回应DanMan,Maarten和Matt。克隆节点,设置文本确实是我的结果中可行的方法。
// @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中的节点,在尝试访问parentNode时返回null。此外,如果您需要保证安全,节点在添加内容之前是空的,这非常有用。考虑下面的用例。
// @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 );
我发现这个方法在替换元素中的字符串时非常有用,如果你不确定节点将包含什么,而不是担心如何清理混乱,那么就开始新鲜了。
答案 11 :(得分:4)
elm.replaceChildren()
这是实验性的,没有广泛的支持,但是在不使用参数的情况下执行将满足您的要求,并且比遍历每个孩子并将其删除要更有效。如前所述,用一个空字符串替换innerHTML将需要在浏览器部分进行HTML解析。
文档here。
答案 12 :(得分:3)
我看到有人在做:
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]);
}
你觉得怎么样?
PS: 这个话题对我来说是一个救生员。我的firefox插件被拒绝了因为我使用了innerHTML。这是一个习惯很长一段时间。然后我发现了这个。我实际上注意到速度差异。在加载时,innerhtml需要花费一些时间来更新,但是它会立即通过addElement进行更新!
答案 13 :(得分:3)
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
}
}
}
这将删除元素中的所有节点。
答案 14 :(得分:3)
有几种方法可以实现这一目标:
最快():
while (node.lastChild) {
node.removeChild(node.lastChild);
}
替代品(较慢):
while (node.firstChild) {
node.removeChild(node.firstChild);
}
while (node.hasChildNodes()) {
node.removeChild(node.lastChild);
}
答案 15 :(得分:2)
innerText是赢家! http://jsperf.com/innerhtml-vs-removechild/133。在所有先前的测试中,父节点的内部dom在第一次迭代时被删除,然后是innerHTML或removeChild,其中应用于空div。
答案 16 :(得分:2)
通过Javascript删除节点子节点的最简单方法
var myNode = document.getElementById("foo");
while(myNode.hasChildNodes())
{
myNode.removeChild(myNode.lastChild);
}
答案 17 :(得分:2)
使用范围循环对我来说是最自然的:
for (var child of node.childNodes) {
child.remove();
}
根据我在Chrome和Firefox中的测量,速度要慢1.3倍。在正常情况下,这可能无关紧要。
答案 18 :(得分:2)
这是我通常要做的:
HTMLElement.prototype.empty = function() {
while (this.firstChild) {
this.removeChild(this.firstChild);
}
}
瞧,以后您可以使用:
清空任何dom元素。anyDom.empty()
答案 19 :(得分:1)
ES6+浏览器的最佳删除方法(2016年后发布的主流浏览器):
也许有很多方法可以做到,例如Element.replaceChildren()。 我想向您展示一个有效的解决方案,其中只有一次重绘和重排支持所有 ES6+ 浏览器。
function removeChildren(cssSelector, parentNode){
var elements = parentNode.querySelectorAll(cssSelector);
let fragment = document.createDocumentFragment();
fragment.textContent=' ';
fragment.firstChild.replaceWith(...elements);
}
用法:removeChildren('.foo',document.body);
:删除foo
中所有className为<body>
的元素
答案 20 :(得分:1)
myNode.querySelectorAll('*').forEach( n => n.remove() );
这回答了问题,并删除了“所有子节点” 。
如果存在属于myNode
的文本节点,则无法使用CSS选择器选择它们,在这种情况下,我们还必须应用:
myNode.textContent = '';
实际上,最后一个可能是最快,更有效/效率更高的解决方案。
.textContent
比.innerText
和.innerHTML
更有效率,请参阅:MDN
答案 21 :(得分:1)
let el = document.querySelector('#el');
if (el.hasChildNodes()) {
el.childNodes.forEach(child => el.removeChild(child));
}
答案 22 :(得分:1)
通常,JavaScript使用数组来引用DOM节点列表。因此,如果您有兴趣通过HTMLElements数组执行此操作,这将很有效。此外,值得注意的是,因为我使用的是数组引用而不是JavaScript原型,这应该可以在任何浏览器中使用,包括IE。
while(nodeArray.length !== 0) {
nodeArray[0].parentNode.removeChild(nodeArray[0]);
}
答案 23 :(得分:0)
为什么我们不遵循这里最简单的方法&#34;删除&#34;在里面打圈。
const foo = document.querySelector(".foo");
while (foo.firstChild) {
foo.firstChild.remove();
}
答案 24 :(得分:0)
刚刚看到有人在另一个问题中提到了这个问题,并以为我会添加一个我还没有看到的方法:
function clear(el) {
el.parentNode.replaceChild(el.cloneNode(false), el);
}
var myNode = document.getElementById("foo");
clear(myNode);
clear函数使用元素并使用父节点将自身替换为没有子元素的副本。如果元素稀疏,则不会有多少性能提升,但是当元素具有一堆节点时,就可以实现性能提升。
答案 25 :(得分:0)
仅适用于功能的方法:
const domChildren = (el) => Array.from(el.childNodes)
const domRemove = (el) => el.parentNode.removeChild(el)
const domEmpty = (el) => domChildren(el).map(domRemove)
domChildren中的“ childNodes”将给出直接子元素的nodeList,如果找不到则为空。为了映射到nodeList,domChildren将其转换为数组。 domEmpty将函数domRemove映射到所有元素上,然后将其删除。
用法示例:
domEmpty(document.body)
从body元素中删除所有子元素。
答案 26 :(得分:0)
您可以从如下所示的容器中删除所有子元素:
function emptyDom(selector){
const elem = document.querySelector(selector);
if(elem) elem.innerHTML = "";
}
现在您可以调用该函数并通过选择器,如下所示:
如果元素的ID为 foo
emptyDom('#foo');
如果元素具有class = foo
emptyDom('.foo');
如果元素具有标签= << strong> div >
emptyDom('div')
答案 27 :(得分:0)
element.innerHTML = ""
(或.textContent)是迄今为止最快的解决方案
例如:
https://jsperf.com/innerhtml-vs-removechild/15 这是一个适当的测试:https://jsperf.com/innerhtml-conspiracy 最后,请勿使用
此测试不会在每次迭代之间向元素添加新的子代。第一次迭代将删除元素的内容,然后其他所有迭代将不执行任何操作。
在这种情况下,while (box.lastChild) box.removeChild(box.lastChild)
速度更快,因为 box.lastChild是null
的{99%的时间}
node.parentNode.replaceChild(node.cloneNode(false), node)
。这会将节点替换为其自身的副本,而不包含其子节点。但是,这不会保留事件侦听器,并且会中断对该节点的任何其他引用。
答案 28 :(得分:0)
如果您想清空整个父级 DOM
那么这很简单...
只需使用 .empty()
function removeAll() {
$('#parent').empty();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button onclick="removeAll()">Remove all the element of parent</button>
<div id="parent">
<h3>Title</h3>
<p>Child 1</p>
<p>Child 2</p>
<p>Child 3</p>
</div>
答案 29 :(得分:-1)
简单快速地使用for循环!
https://bar.com.s/media/hgfr2um5oqibs8lbjbv7.jpg
这在var myNode = document.getElementById("foo");
for(var i = myNode.childNodes.length - 1; i >= 0; --i) {
myNode.removeChild(myNode.childNodes[i]);
}
标签中不起作用!
答案 30 :(得分:-1)
最简单的方法:
let container = document.getElementById("containerId");
container.innerHTML = "";
答案 31 :(得分:-1)
只是IE:
parentElement.removeNode(true);
true
- 意味着深度移除 - 这意味着所有孩子也被移除
答案 32 :(得分:-1)
jQuery中的其他方法
var foo = $("#foo");
foo.children().remove();
or
$("*", foo ).remove();
or
foo.html("");
答案 33 :(得分:-3)
如果您想将某些内容放回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
方法没有问题。
答案 34 :(得分:-4)
这是一个纯粹的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 ="";
})
答案 35 :(得分:-7)
使用jQuery:
$("#foo").find("*").remove();