Internet Explorer 11非常缓慢地将元素附加到DOM

时间:2017-03-24 15:34:54

标签: javascript internet-explorer dom appendchild

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

我尝试过使用与这些

类似的三种不同方法

&#13;
&#13;
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);
}
&#13;
<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>
&#13;
&#13;
&#13;

方法1)创建元素并直接插入DOM;

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

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

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

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

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

使用方法2(首先附加到文档片段)我可以在分析器中看到它需要不到一秒的时间来准备片段,但需要23秒才能将片段附加到DOM。分析器显示了很多&#34; DOM事件(DOMNodeInserted)&#34;事件后跟&#34;垃圾收集&#34;。其中可能有40个。注意:此配置文件来自应用程序,而不是代码段。

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

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

为什么要触发DOMNodeInserted事件?

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

为什么探查器会在每秒或第三次事件中显示3秒的间隙(各个位的时间不相加)?

我的代码可以改进吗?

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

2 个答案:

答案 0 :(得分:3)

事实证明,它是分析器或更具体地说F12工具打开导致它减速。我的初始代码很慢,所以我在优化时使用了配置文件。如果其他人遇到类似的问题我会留下这个问题。

答案 1 :(得分:0)