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

新手上路,请多包涵

我将如何在 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 的答案,则可以加分。

原文由 Polaris878 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.6k
2 个回答

选项 1 A:清除 innerHTML

  • 这种方法很简单,但可能不适合高性能应用程序,因为它会调用浏览器的 HTML 解析器(尽管浏览器 可能会 针对值为空字符串的情况进行优化)。
 doFoo.onclick = () => {
 const myNode = document.getElementById("foo");
 myNode.innerHTML = '';
 }
 <div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
 <span>Hello</span>
 </div>
 <button id='doFoo'>Remove via innerHTML</button>

选项 1 B:清除 textContent

  • 如上所述,但使用 .textContent根据 MDN, 这将比 innerHTML 更快,因为浏览器不会调用它们的 HTML 解析器,而是会立即将元素的所有子元素替换为单个 #text 节点。
 doFoo.onclick = () => {
 const myNode = document.getElementById("foo");
 myNode.textContent = '';
 }
 <div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
 <span>Hello</span>
 </div>
 <button id='doFoo'>Remove via textContent</button>

选项 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; width: 100px; border: 1px solid black;">
 <span>Hello</span>
 </div>
 <button id='doFoo'>Remove via 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; width: 100px; border: 1px solid black;">
 <!-- This comment won't be removed -->
 <span>Hello <!-- This comment WILL be removed --></span>
 <!-- But this one won't. -->
 </div>
 <button id='doFoo'>Remove via lastElementChild-loop</button>

奖励: Element.clearChildren 猴子补丁:

  • 我们可以在 JavaScript 中向 Element 原型添加一个新的方法属性,以简化对它的调用,只需 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>

原文由 Gabriel McAdams 发布,翻译遵循 CC BY-SA 4.0 许可协议

选项 1 A:清算 innerHTML

  • 这种方法很简单,但可能不适合高性能应用程序,因为它会调用浏览器的 HTML 解析器(尽管浏览器 可能会 针对值为空字符串的情况进行优化)。
 doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  myNode.innerHTML = '';
}
 <div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via innerHTML</button>

选项 1 B:清除 textContent

  • 同上,但使用 .textContent根据 MDN, 这将比 innerHTML 更快,因为浏览器不会调用它们的 HTML 解析器,而是立即将元素的所有子元素替换为单个 #text 节点。
 doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  myNode.textContent = '';
}
 <div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via textContent</button>

选项 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; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via 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; width: 100px; border: 1px solid black;">
  <!-- This comment won't be removed -->
  <span>Hello <!-- This comment WILL be removed --></span>
  <!-- But this one won't. -->
</div>
<button id='doFoo'>Remove via lastElementChild-loop</button>

奖金: Element.clearChildren 猴子补丁:

  • 我们可以在 JavaScript 中的 Element 原型中添加一个新的方法属性,以简化对 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>

原文由 Gabriel McAdams 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题