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

Remove all child elements of a DOM node in JavaScript

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

假设我有以下(丑陋的)HTML:

1
2
3
4
5
<p id="foo">
    <span>hello</span>
    world

</p>

我抓取我想要的节点,就像这样:

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

我怎样才能去掉EDOCX1的子代(0),只剩下EDOCX1的子代(1)?

我可以这样做吗:

1
myNode.childNodes = new Array();

还是应该使用removeElement的组合?

我希望答案是直接向上的dom;不过,如果您在jquery中也提供了答案以及dom-only答案,则需要额外的分数。


选项1(速度慢得多,请参阅下面的注释):

1
2
var myNode = document.getElementById("foo");
myNode.innerHTML = '';

选项2(更快):

1
2
3
4
var myNode = document.getElementById("foo");
while (myNode.firstChild) {
    myNode.removeChild(myNode.firstChild);
}


当前接受的答案是错误的,因为innerhtml速度较慢(至少在IE和Chrome中),正如M93A正确提到的。

chrome和ff使用此方法的速度显著加快(这将破坏附加的jquery数据):

1
2
var cNode = node.cloneNode(false);
node.parentNode.replaceChild(cNode ,node);

在远处的一秒钟内出现FF和Chrome,在IE中最快:

1
node.innerHTML = '';

InnerHTML不会破坏事件处理程序或中断jquery引用,这里还建议将其作为解决方案:https://developer.mozilla.org/en-us/docs/web/api/element.innerhtml网站

最快的DOM操作方法(仍然比前两种方法慢)是删除范围,但直到IE9才支持范围。

1
2
3
var range = document.createRange();
range.selectNodeContents(node);
range.deleteContents();

上面提到的其他方法似乎具有可比性,但比innerhtml慢得多,除了离群值jquery(1.1.1和3.1.1),它比其他方法慢得多:

1
$(node).empty();

证据如下:

http://jspef.com/innerhtml vs removechild/167http://jspef.com/innerhtml vs removechild/300https://jspef.com/remove-all-child-elements-of-a-dom-node-in-javascript(因为编辑旧的URL不起作用,所以jsper重新启动的新URL)

JSperf的"每个测试循环"通常被理解为"每个迭代",只有第一个迭代有要删除的节点,所以结果是无意义的,在发布时,这个线程中的测试设置不正确。


1
2
3
4
5
6
7
var myNode = document.getElementById("foo");
var fc = myNode.firstChild;

while( fc ) {
    myNode.removeChild( fc );
    fc = myNode.firstChild;
}

如果您有任何机会让jquery影响后代,那么您必须使用一些方法来清理jquery数据。

1
$('#foo').empty();

jquery .empty()方法将确保清除jquery与要删除的元素相关联的任何数据。

如果只使用DOM方法删除子对象,那么数据将保留。


如果使用jquery:

1
$('#foo').empty();

如果你不这样做:

1
2
var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);


使用现代的javascript,与remove

1
2
3
4
const parent = document.getElementById("foo");
while (parent.firstChild) {
    parent.firstChild.remove();
}

这是一种在ES5中写入节点删除的新方法。它是普通的JS,读起来比以前的版本好得多。

大多数用户应该有现代的浏览器,或者你可以在需要的时候发泄出来。

浏览器支持-2019年4月93%


最快的…

1
2
3
4
var removeChilds = function (node) {
    var last;
    while (last = node.lastChild) node.removeChild(last);
};

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

编辑:要清楚,firstchild和lastchild在chrome中没有性能差异。上面的答案显示了一个很好的性能解决方案。


如果只想让节点不带子节点,也可以这样复制它:

1
var dupNode = document.getElementById("foo").cloneNode(false);

取决于你想要达到的目标。


1
element.textContent = '';

除了标准外,它和InnerText很像。它比removeChild()慢一点,但是它更容易使用,如果没有太多要删除的内容,也不会对性能产生太大影响。


另一种方法是:

1
2
3
4
5
6
7
8
9
10
11
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();
}


作为对丹曼、马顿和马特的回应。克隆一个节点,设置文本在我的结果中确实是一种可行的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// @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时返回空值。此外,如果需要确保安全,则在添加内容之前节点是空的,这非常有用。考虑下面的用例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// @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 );

当替换元素中的字符串时,我发现这个方法非常有用,如果您不确定节点将包含什么,那么不用担心如何清理混乱,而是从新开始。


我看到人们在做:

1
2
3
while (el.firstNode) {
    el.removeChild(el.firstNode);
}

然后有人说使用el.lastNode更快

不过,我认为这是最快的:

1
2
3
4
var children = el.childNodes;
for (var i=children.length - 1; i>-1; i--) {
    el.removeNode(children[i]);
}

你怎么认为?

PS:这个话题对我来说是个救命稻草。我的火狐插件被拒绝了,因为我使用了innerhtml。长期以来它一直是一种习惯。然后我发现了这个。实际上我注意到了一个速度差。加载时,innerhtml花了一段时间进行更新,但是addelement会立即更新!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
        }
    }
}

这将删除元素中的所有节点。


实现这一点有两种选择:

最快():

1
2
3
while (node.lastChild) {
  node.removeChild(node.lastChild);
}

备选方案(较慢):

1
2
3
4
5
6
7
while (node.firstChild) {
  node.removeChild(node.firstChild);
}

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

以建议的选项为基准


使用范围循环对我来说最自然:

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

根据我在Chrome和Firefox上的测量,它慢了1.3倍。在正常情况下,这也许无关紧要。


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

1
2
3
4
5
var myNode = document.getElementById("foo");
while(myNode.hasChildNodes())
{
   myNode.removeChild(myNode.lastChild);
}

我通常做的是:

1
2
3
4
5
HTMLElement.prototype.empty = function() {
    while (this.firstChild) {
        this.removeChild(this.firstChild);
    }
}

和voila,稍后您可以使用以下命令清空任何dom元素:

1
anyDom.empty()

InnerText是赢家!http://jspef.com/innerhtml-vs-removechild/133。在所有以前的测试中,父节点的内部dom在第一次迭代时被删除,然后在应用于空的div时被innerhtml或removechild删除。


通常,javascript使用数组来引用dom节点列表。因此,如果您有兴趣通过htmlelements数组来实现这一点,那么这将很好地工作。另外,值得注意的是,因为我使用的是数组引用,而不是javascript协议,这应该在任何浏览器中都可以使用,包括IE。

1
2
3
while(nodeArray.length !== 0) {
  nodeArray[0].parentNode.removeChild(nodeArray[0]);
}

为什么我们不按照最简单的方法来"删除"这个循环。

1
2
3
4
const foo = document.querySelector(".foo");
while (foo.firstChild) {
  foo.firstChild.remove();    
}
  • 选择父分区
  • 在while循环中使用"remove"方法来消除第一个子元素,直到没有剩余元素为止。


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

1
2
3
4
5
6
function clear(el) {
    el.parentNode.replaceChild(el.cloneNode(false), el);
}

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

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


最简单的方法:

1
2
let container = document.getElementById("containerId");
container.innerHTML ="";


仅仅是IE:

1
parentElement.removeNode(true);

true表示进行深度切除,也就是说所有的孩子都被切除。


jquery中的其他方法

1
2
3
4
5
6
var foo = $("#foo");
foo.children().remove();
or
$("*", foo ).remove();
or
foo.html("");


简单快速的循环使用!!

1
2
3
4
5
var myNode = document.getElementById("foo");

    for(var i = myNode.childNodes.length - 1; i >= 0; --i) {
      myNode.removeChild(myNode.childNodes[i]);
    }

这在标签中不起作用!


如果你想把东西放回那个divinnerHTML可能更好。

我的例子:

1
2
3
4
5
6
7
8
9
10
11
12
<ul>

</ul>



  function displayHTML(result){
    var movieLink = document.createElement("li");
    var t = document.createTextNode(result.Title);
    movieLink.appendChild(t);
    outputDiv.appendChild(movieLink);
  }

如果我使用.firstChild.lastChild方法,那么displayHTML()函数在随后不会工作,但对.innerHTML方法没有问题。


这是一个纯粹的javascript,我不使用jquery,但在所有浏览器中都可以使用,甚至是IE,而且非常容易理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    <p>
Paragraph one
</p>
    <p>
Paragraph two
</p>
    <p>
Paragraph three
</p>
   
   <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 ="
";

})

使用jQuery:

1
$("#foo").find("*").remove();