2017-03-24 74 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

相關問題