3

我正在通过 ajax 调用在 div 中加载 .html 文件的全部数据。html 页面包含HTC(html 组件)与页面上的元素绑定所需的链接、脚本标签。

页面结构如下:

在此处输入图像描述 我正在使用 jQuery 加载这样的 HTML 页面

<body>
<input type="radio" class="openpage" id="0001">
<input type="radio" class="openpage" id="0002">
<input type="radio" class="openpage" id="0003">
<input type="radio" class="openpage" id="0004">

<div id="loadPage"></div>
<script>
$(document).ready(function(){
  $(".openpage").on("click",function(){
    $("#loadPage").load($(this).attr("id")+".html",function(){
    //load a page with many htc bindings and external references

    //trigger some onload functions which are not called automatically in IE
    //confirmed this is in chrome

    });
  });
})
</script>

</body>

这样做的问题是 IE 内存不断堆积,因为单击单选按钮以加载页面,并且在加载几个页面后浏览器停止响应。我可以在任务管理器中看到内存在增加。

该应用程序在 IE 5、6、7、8、9 和 IE10 的怪癖模式下运行。我试图在 chrome 中复制相同的场景,它显示没有问题。所以我认为这是 IE 特定的内存管理相关问题。

我读了很多文章,但我不相信。我也在 SO 上读过这个问题,但它建议只加载页面的一部分,这在我的情况下是不可接受的。这篇文章似乎相关,但我不确定究竟是什么导致内存泄漏我的情况。

上面的整个主体实际上是在一个 iframe中。因此,作为一种解决方法,我在单击 8 次单选按钮后重新加载包含主页的框架。我试图在每次加载之前清除东西:

$("#loadPages").empty();

$("#loadPages").find("*").off();

$.ajaxSetup({ cache: false });

但是没有任何效果。所以我怀疑jquery是否可以清除通过htc注册的事件。

1)如果你能解释一下这种情况下内存泄漏的原因,那就太好了。

2)通常为什么加载许多资源后浏览器会发生内存泄漏。这在现代浏览器中不会发生,但为什么会在旧浏览器中发生。

3)有没有办法在不刷新框架的情况下释放浏览器内存。

4)有没有办法检查浏览器内存中的所有资源。

4

2 回答 2

4

您有几个工作流程:

  • 用动态加载的结构替换现有的 DOM 结构。
  • 加载后连接额外的事件处理。

从这里:

  • 移除/替换 DOM 节点时,仍然绑定事件
  • 通过绑定到事件处理程序,DOM 节点可能无法清除
  • DOM 节点保留在内存中,与 UI 分离,但仍会泄漏内存。

您的选择是:

  • 确保在从 DOM 中清除这些节点之前清除现有结构上的所有事件,并允许加载新内容。
  • 有多个显示节点,每个节点只加载一次。
  • 检查一个节点是否存在,然后简单地分离它,而不是尝试替换它。

IE 为 JavaScript 和渲染引擎提供了单独的 COM 通道,这意味着有时,尤其是事件绑定。JS 中的对象/状态可以保留对 UI/DOM 节点的引用......并且 DOM 节点可以引用 JS 事件处理程序。在许多情况下,这意味着这些部分不会被垃圾收集,从而导致内存使用量膨胀。早期版本的情况要糟糕得多,但仍然会发生。

您可能在其他浏览器中遇到类似问题,但 IE 往往会更快地显示此行为。长寿命的单页应用程序也会发生这种情况。

如果您只将每个资源加载一次,将其加载到其自己的 DOM 节点中,您可以简单地分离/重新附加该节点。此外,您可以依靠事件传播来侦听来自父节点的事件。这些中的任何一个都将减少争用的风险和开销。

至于取消注册您的事件处理程序,只要您使用 jQuery 注册,并使用 jQuery 删除/删除节点(及其子节点),jQuery 在这方面做得比大多数都好。

于 2015-02-24T22:18:10.020 回答
1

你有没有考虑过使用 xhr 请求?他们可以使用 ajax 将内容加载到您的目标。我对你的问题做了一个样本小提琴。看看它。干杯。

片段

function getXmlHttpRequest() {
  var xmlhttp;
  if (window.XMLHttpRequest) {
    xmlhttp = new XMLHttpRequest();
    // code for IE7+, Firefox, Chrome, Opera, Safari

  } else if (window.ActiveXObject) {
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    // code for IE5 and IE6
  } else {
    alert("Browser doesn't support Ajax..!!");
  }

  return xmlhttp;
}

function loadPage(pageTitle) {
  //pageTitle = pageTitle + ".html";
  xmlhttp = getXmlHttpRequest();
  if (xmlhttp != null) {
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState < 4) {
        document.getElementById('loadPage').innerHTML = "Content Loading...!";
      } else if (xmlhttp.readyState == 4) {
        var res = xmlhttp.responseText;
        document.getElementById('loadPage').innerHTML = res;
      }
    }
    xmlhttp.open("GET", pageTitle, true);
    xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xmlhttp.send(null);
  }
}

function showAlert() {
  alert("This is me!");
}
$(document).ready(function() {
  $(".openpage").on("click", function() {
    loadPage($(this).attr("id"));
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<input type="radio" class="openpage" name="radio-group" id="https://dl.dropboxusercontent.com/u/105580681/xhr-fiddle/0001.html">
<input type="radio" class="openpage" name="radio-group" id="https://dl.dropboxusercontent.com/u/105580681/xhr-fiddle/0002.html">
<input type="radio" class="openpage" name="radio-group" id="https://dl.dropboxusercontent.com/u/105580681/xhr-fiddle/0003.html">
<input type="radio" class="openpage" name="radio-group" id="https://dl.dropboxusercontent.com/u/105580681/xhr-fiddle/0004.html">
<div id="loadPage"></div>

在这个小提琴中,我正在使用 Dropbox 链接加载 html 文件。您可以使用 0001 - 0004 id 编号的最初想法。
但是,如果您正在加载 html 页面的全部内容,这将加载从该外部 html 页面到目标主页内部的所有内容。

例子:

<div id="loadPage">
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <div>Content of HTML 0001 Page</div>
</div>

这将影响到您的主页面的 DOM 文件。页面功能不会松动,但它不是一种好的编程技术。因此,您可能需要在 xxxx.html 文件中写入或加载要在目标元素上显示的内容。 从使用 XMLHttpRequest

了解更多信息Mozilla MDN使用 FormData 对象 Mozilla MDN

于 2015-02-27T01:52:15.537 回答