什么是在JavaScript中清空一个节点的最佳方法?

15

我有一个带有大量缩略图的图库。为了防止DOM被节点填满,我正在重复使用它们。在不使用库的情况下,最好的方法是从DOM中删除节点是什么?

使用 innerHTML = "" 将解析并创建一个新的空文本节点,但循环和删除子节点会导致重新渲染。


node.innerHTML = "" 不会创建一个新的空节点,而是清空了 node - Alvin Wong
如果您正在重复使用它们,为什么要尝试将它们删除?您是想替换HTML元素中的缩略图吗?如果是这样,请在img元素上设置href属性即可。 - Bruno
我正在池化节点以供稍后重用。 - user920041
1
@IntoTheVoid:“应用程序不会刷新,因此为了避免内存问题,我正在尽量减少节点创建。” 顺便说一句,除非您真正遇到实际的、可感知的问题需要解决,否则我建议让浏览器自行处理内存管理。 - T.J. Crowder
@IntoTheVoid:“使用innerHTML =“”将解析并创建一个新的空文本节点…” 不,不会创建文本节点。但它似乎会启动HTML解析器,即使字符串为空-或者至少,某些东西需要一些时间。 - T.J. Crowder
显示剩余3条评论
3个回答

19

您至少有四种选择:

  1. 使用如问题中展示的 innerHTML = ""。它会确保调用它的元素没有任何子节点,并且不会创建任何新节点。它是指定和跨浏览器可靠的(尽管存在可能影响您的代码的IE bug),并且可能相当高效。

  2. 使用 textContent = "",它也是指定和跨浏览器可靠的(IE9+),有趣的是,至少在IE11上看起来没有与 innerHTML 相关的bug,但是却具有优点,即不需要HTML解析器,而当然你给出的字符串应该是HTML。 (浏览器可能已经针对字符串为空时进行了优化。)

  3. 您可以在循环中使用 removeChild,但这涉及到对DOM进行潜在的重复函数调用:

    // assuming elm is the element
    while (elm.firstChild) {
       elm.removeChild(elm.firstChild);
    }
    
  4. 您可以使用克隆元素替换父元素,不包括子元素:

  5. // assuming elm is the element
    const clone = elm.cloneNode(false);
    parent.parentElement.replaceChild(clone, elm);
    elm = clone;
    

    请注意,与其他方法不同的是,这种方法将删除父元素上的任何事件处理程序。

如果我必须猜测,我会猜测textContent = ""是最快的,至少在有 很多子元素的情况下是这样。但是性能通常并不重要,只有在极少数情况下,这才会成为您代码明显缓慢的部分。如果您遇到需要考虑性能的情况,请在目标浏览器中测试每个选项的实际代码,并选择最佳选项。

人们喜欢使用人工基准测试,但是人工基准测试非常不可靠,并且对基准假设(例如要删除的子元素数量)非常敏感。


3

如果您想清空一个元素,您也可以直接调用node.replaceChildren()方法。这种方法非常快速、干净,并且能够清晰地表达您的意图。


这是正确的答案,对我完美地起作用。 - C Alonso C Ortega
@CAlonsoCOrtega 你能详细解释一下为什么这个方案比被接受的解决方案更优越吗? - undefined

0
function clearNode(node, clone = true) {
  let emptyNode;

  if (clone) {
    emptyNode = node.cloneNode();
    node.parentNode.replaceChild(emptyNode, node);
    node = emptyNode;
  }
  else {
    while (node.hasChildNodes()) {
      node.removeChild(node.firstChild);
    }
    emptyNode = node;
  }

  return emptyNode;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接