2017-03-24 31 views
0

我有一个网页,通过ajax调用加载数据,然后填充一个“表”。它实际上使用'div'元素作为一行,更多'div'元素作为单元格。为了测试目的,我没有将这些div应用于任何样式或类,它们仅仅是:<div><div>cell1</div><div>cell2</div></div>。在测试过程中,我加载了2000行,每行5列。互联网资源管理器11非常缓慢追加元素到DOM

我已经采用类似于这些

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++) { 
 
\t \t 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>

方法1)创建的元素和直接插入到DOM三种不同方法试图;

方法2)创建一个文档片段并追加到该文件中。在最后插入片段到DOM;

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

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

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

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

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

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

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

它为什么会触发DOMNodeInserted事件?

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

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

我的代码可以改进吗?

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

+0

在此处发布您的代码,而不仅仅是在远程站点。您可以使用[Stack Snippets](https://stackoverflow.blog/2014/09/introducing-runnable-javascript-css-and-html-code-snippets/)使其可执行。 – Barmar

回答

2

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

+0

感谢您的跟进! appendChild接近800毫秒,我无法弄清楚为什么。在关闭开发人员工具并执行警报而不是console.log来查看持续时间后,仅花费60毫秒。 – caseyjhol