【问题标题】:Internet Explorer 11 very slow appending elements to DOMInternet Explorer 11 向 DOM 追加元素的速度非常慢
【发布时间】:2017-03-24 15:34:54
【问题描述】:

我有一个网页,它通过 ajax 调用加载数据,然后填充一个“表格”。它实际上使用 'div' 元素作为行和更多的 'div' 元素作为单元格。出于测试目的,我没有对这些 div 应用任何样式或类,它们只是:<div><div>cell1</div><div>cell2</div></div>。在测试期间,我加载了 2000 行,每行 5 列。

我尝试过使用与这些类似的三种不同方法

function test(method) {

var totalRows = 2000;
var totalCols = 6;
var rows = [];
var r, c, row, cell;

for (r = 0; r < totalRows; r++) {
  row = [];
  rows.push(row);
  for (c = 0; c < totalCols; c++) {
    row.push(r + ':' + c + ' Just some text');
  }
}

var container = document.getElementById('container');
var output = document.getElementById('output');
var div = document.createElement('div');

container.innerHTML = '';

var start = new Date().getTime();
switch (method) {
case 1:
  for (r = 0; r < totalRows; r++) {
    row = div.cloneNode(false);
    container.appendChild(row);

    for (c = 0; c < totalCols; c++) {
      cell = div.cloneNode(false);
      cell.appendChild(document.createTextNode(rows[r][c]));
      row.appendChild(cell);
    }
  }
  break;
case 2:
  var outer = document.createElement('div');
  var frag = document.createDocumentFragment();
  for (r = 0; r < totalRows; r++) {
    row = div.cloneNode(false);
    frag.appendChild(row);

    for (c = 0; c < totalCols; c++) {
      cell = div.cloneNode(false);
      cell.appendChild(document.createTextNode(rows[r][c]));
      row.appendChild(cell);
    }
  }
  container.appendChild(frag);
  break;
case 3:
  var els = [];
  for (r = 0; r < totalRows; r++) {
		els.push('<div>');
    for (c = 0; c < totalCols; c++) {
      els.push('<div>');
      els.push(rows[r][c]);
      els.push('</div>');
    }
    els.push('</div>');
  }
  // ignore string creation
  start = new Date().getTime();
  container.innerHTML = els.join('');
  break;
}
var end = new Date().getTime();
output.innerHTML = 'time: ' + (end - start);
}
<input type="button" value="Method 1 (Direct)" onclick="test(1)"><br>
<input type="button" value="Method 2 (Fragment)" onclick="test(2)"><br>
<input type="button" value="Method 3 (innerHTML)" onclick="test(3)"><br>

<div id="output"></div>
<div id="container">
</div>

方法一)创建元素并直接插入到DOM中;

方法 2) 创建一个文档片段并附加到其中。最后将片段插入 DOM;

方法 3) 创建文本 HTML 表示并设置 innerHTML。

在前两种方法中,我是克隆元素而不是创建它们。

我在这部分使用纯 JavaScript。这些示例使用 Firefox 运行得非常快,全部都在 40 毫秒以下。使用 IE 11,前两种方法运行时间约为 2000 毫秒,而第三种方法运行时间为 150 毫秒。这对我的需要是可以接受的。

当我在实际的 Web 应用程序中尝试这些方法时,就会出现问题。 “表”嵌套在一个更复杂的结构中。不幸的是,我提供一个工作示例太复杂了。表本身保留完全相同的结构。使用 Firefox 时,表格会在大约 1 秒后显示(在从服务器获取数据之后)。这是可以接受的。然而,IE 需要 20 多秒,而我使用三种方法中的哪一种几乎没有区别。

使用方法 2(首先附加到文档片段)我可以在分析器中看到准备片段需要不到一秒的时间,但将片段附加到 DOM 需要 23 秒。分析器显示大量“DOM 事件 (DOMNodeInserted)”事件,然后是“垃圾收集”。其中可能有40个。注意:此配置文件来自应用程序,而不是代码 sn-p。

屏幕截图显示了这些条目。

分析器将 GC 条目标记为 JavaScript 垃圾收集(而不是一些内部 IE 内容)。我的问题是:

为什么会触发 DOMNodeInserted 事件?

GC 的工作是什么(此时没有变量超出范围)?

为什么分析器每隔第二个或第三个事件显示 3 秒的间隔(各个位的时间不相加)?

我的代码可以改进吗?

我已经尝试了所有我能想到的优化,包括:在构建时将样式显示设置为无;克隆节点而不是创建它们;并在循环之外声明变量。据我推断,我没有将任何事件监听器附加到 DOM 的这一部分。

【问题讨论】:

  • 在此处发布您的代码,而不仅仅是在远程站点。您可以使用Stack Snippets 使其可执行。

标签: javascript internet-explorer dom appendchild


【解决方案1】:

原来是分析器或者更具体地说是打开 F12 工具导致它变慢。我的初始代码很慢,所以我在优化时使用了配置文件。如果其他人有类似的问题,我会留下问题。

【讨论】:

  • 感谢您的跟进! appendChild 接近 800 毫秒,我不知道为什么。关闭开发人员工具并发出警报而不是 console.log 以查看持续时间后,只需要 60 毫秒。
  • 好吧,这将单个 DOM 元素的附加从约 6 秒降低到基本难以察觉。不错!
【解决方案2】:

【讨论】:

  • 这并没有提供问题的答案。请改写评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-09
  • 2014-11-10
  • 1970-01-01
  • 2017-11-01
  • 2021-09-06
  • 1970-01-01
相关资源
最近更新 更多