首页 文章

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

提问于
浏览
629

我如何在JavaScript中删除DOM节点的所有子元素?

说我有以下(丑陋的)HTML:

<p id="foo">
    <span>hello</span>
    <div>world</div>
</p>

我 grab 了我想要的节点:

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

我怎么能删除 foo 的子项以便只留下 <p id="foo"></p>

我能这样做吗:

myNode.childNodes = new Array();

或者我应该使用 removeElement 的某些组合?

我希望答案是直接的DOM;如果您还在jQuery中提供答案以及仅限DOM的答案,那么可以获得额外的分数 .

27 回答

  • 82

    使用现代Javascript,删除!

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

    这是在ES5中编写节点删除的更新方法 . 它是vanilla JS,读起来比以前的版本好多了 .

    大多数用户应该使用现代浏览器,或者您可以根据需要进行调整 .

    Browser Support - 2018年4月91%

  • -1

    如果您只想让节点没有子节点,您也可以像这样复制它:

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

    取决于你想要实现的目标 .

  • 40

    我看到有人这样做:

    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进行更新!

  • 1254

    只是IE:

    parentElement.removeNode(true);
    

    true - 意味着深度删除 - 这意味着所有孩子也被删除

  • 3

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

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

    最简单的方法:

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

    为什么我们不遵循这里最简单的方法“删除”循环内部 .

    const foo = document.querySelector(".foo");
    while (foo.firstChild) {
      foo.firstChild.remove();     
    }
    
    • 选择父div

    • 在While循环中使用"remove"方法消除第一个子元素,直到没有剩余 .

  • 2
    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 方法删除子项,则该数据将保留 .

  • 5

    最快的...

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

    感谢Andrey Lushnikov为his link to jsperf.com(很酷的网站!) .

  • 5
    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

    有几种方法可以实现这一目标:

    最快的 ():

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

    替代方案(较慢):

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

    Benchmark with the suggested options

  • -3

    通常,JavaScript使用数组来引用DOM节点列表 . 因此,如果您有兴趣通过HTMLElements数组执行此操作,这将很有效 . 另外,值得注意的是,因为我使用的是数组引用而不是JavaScript proto,所以这应该适用于任何浏览器,包括IE .

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

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

  • 9

    用jQuery:

    $("#foo").find("*").remove();
    
  • 32

    jQuery中的其他方法

    var foo = $("#foo");
    foo.children().remove();
    or
    $("*", foo ).remove();
    or
    foo.html("");
    
  • -1

    这是一个纯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 ="";
    
    })
    
  • 4

    这是另一种方法:

    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();
    }
    
  • -5

    这是我通常做的事情:

    HTMLElement.prototype.empty = function() {
        while (this.firstChild) {
            this.removeChild(this.firstChild);
        }
    }
    

    瞧,以后你可以用以下方法清空任何dom元素:

    anyDom.empty()
    
  • 2

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

    function clear(el) {
        el.parentNode.replaceChild(el.cloneNode(false), el);
    }
    
    var myNode = document.getElementById("foo");
    clear(myNode);
    

    clear函数使用元素并使用父节点将其自身替换为没有子元素的副本 . 如果元素稀疏,但是当元素具有一堆节点时,性能增益得以实现,性能增益不大 .

  • 1
    element.textContent = '';
    

    它's like innerText, except standard. It'比 removeChild() ,但如果你没有太多东西需要删除,那么's easier to use and won' t会产生很大的性能差异 .

  • -3

    回应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 );
    

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

  • 0

    如果你想把某些东西放回 divinnerHTML 可能会更好 .

    我的例子:

    <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 方法没有问题 .

  • -1

    如果你使用jQuery:

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

    如果你不这样做:

    var foo = document.getElementById('foo');
    while (foo.firstChild) foo.removeChild(foo.firstChild);
    
  • 0

    选项1(慢得多,见下面的评论):

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

    选项2(很多快点):

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

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

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

    根据我在Chrome和Firefox中的测量结果,它慢了1.3倍 . 在正常情况下,这可能无关紧要 .

  • 3

    简单快速的循环使用!!

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

    这在 <span> 标签中不起作用!

  • 16

    目前接受的答案是关于innerHTML较慢(在IE和Chrome中至少)的错误,正如m93a正确提到的那样 .

    使用此方法可以大大加快Chrome和FF的速度(这会破坏附加的jquery数据):

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

    在FF和Chrome的遥远的第二,在IE中最快:

    node.innerHTML = '';
    

    InnerHTML won't destroy your event handlers or break jquery references ,这里也建议作为解决方案: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重启的新网址,因为编辑旧网址不起作用)

    Jsperf的“per-test-loop”通常被理解为“per-iteration”,只有第一次迭代才有删除的节点,因此结果毫无意义,在发布时,此线程中的测试设置不正确 .

相关问题