【问题标题】:Removing an element from DOM从 DOM 中移除一个元素
【发布时间】:2009-09-25 21:24:27
【问题描述】:

我使用这种方法在客户端转义 HTML 代码字符串:

function escapeHTML(str)
{
   var div = document.createElement('div');
   var text = document.createTextNode(str);
   div.appendChild(text);
   return div.innerHTML;
}; 

我有点担心内存泄漏,因为我正在创建 DOM 元素而不是破坏它。该页面大量使用 Ajax 并且很少刷新,因此可能会在没有重新加载页面的情况下对该方法进行数百次调用,这意味着这些对象将堆积起来,从而减慢 DOM 遍历(例如使用 jQuery)

我尝试使用document.removeChild(div),但 IE 报错“htmlfile: Invalid argument”。

有什么想法吗?

谢谢, 安德烈

【问题讨论】:

    标签: javascript html dom


    【解决方案1】:

    您需要在元素本身上调用removeChild

    function escapeHTML(str) {
       var div = document.createElement('div');
       var text = document.createTextNode(str);
       div.appendChild(text);
       var escapedHTML = div.innerHTML;
       div.removeChild(text);
       return escapedHTML;
    }
    

    要记住的一点是,此解决方案在某些浏览器中存在问题(例如处理换行符 = "\n")。在 Prototype.js 中,我们explicitly check for some of these quirks 并适当地调整逻辑。

    当然,您应该使用特征检测,而不是浏览器嗅探;)

    您也不需要在每次调用函数时都创建新元素。只需将其存放在封闭装置中。例如:

    var escapeHTML = (function(){
    
      var div = document.createElement('div');
      var text = document.createTextNode('');
    
      div.appendChild(text);
    
      return function(str) {
        text.data = str;
        return div.innerHTML;
      };
    })();
    

    如果您采用这种方法并永久保留元素,您还可以在页面卸载时考虑清理它(即nulling),以防止可能的泄漏。

    不幸的是,仅注册卸载事件处理程序会阻止快速导航(又名页面缓存)在许多浏览器中。大多数 JS 库已经观察到该事件以进行清理,因此如果您正在使用一个(例如 Prototype.js、jQuery、YUI),您不必担心它 - 无论如何页面缓存都会被禁用。

    否则,您可能需要重新考虑您的选择,要么总是在运行时创建元素,要么完全采用不同的解决方案(例如基于String.prototype.replace 的解决方案):

    function escapeHTML(str) {
      return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
    }
    

    哦,最后,你不需要放置“;”在函数声明之后; 函数表达式建议以分号结尾:)

    【讨论】:

    • 很久以来我在 SO 上看到的最佳答案之一!
    • 超越。很好的答案。
    • 好答案。关于最后一段:具有讽刺意味的是,您在一个函数表达式之后错过了一个分号:)
    • @Tim Down 哈!是的,确实具有讽刺意味。会修复。这就是代码审查很重要的原因:)
    • 我确定这是我没有正确理解 DOM,但我不理解您的第一个示例。创建了两个对象(一个元素和一个文本节点),但只删除了其中一个。如果曾经存在过,那么问题肯定仍然存在。但是,一开始就存在问题吗?正在创建一个对象,然后将其分配给一个局部变量。当函数退出并且局部变量超出范围时,该对象不会被垃圾收集吗?好久没考虑栈和堆的问题了,有点生疏请见谅!
    【解决方案2】:

    如果你加载了 jQuery,你可以使用remove method

    【讨论】:

      【解决方案3】:

      DOM:

      var node = document.getElementById('node_to_delete');
      node.parentNode.removeChild(node);
      

      jQuery:

      $('#node_to_delete').remove();
      

      【讨论】:

        【解决方案4】:

        IIRC 你不应该关心,因为 JS 是垃圾收集的。如果这是一笔大交易,您可以尝试以非常短的间隔解析通过 setTimeout() 调用的块。

        【讨论】:

        • 我应该补充一点,因为您的 div 从未添加到文档元素中,因此它绝不是文档 DOM 的一部分。
        猜你喜欢
        • 2013-07-20
        • 2012-02-08
        • 2017-05-13
        • 1970-01-01
        • 2014-05-04
        • 2020-03-09
        • 2011-06-11
        • 2012-09-13
        相关资源
        最近更新 更多