2011-03-23 56 views
2

我有一個關於頁面速度和代碼優化的問題。我有一個通過AJAX調用幾乎100%填充的頁面。我的問題是:對我來說,編寫幾個空的div,跨度,到網頁的HTML中,然後用javascript填充這些元素會更快嗎?或者,在javascript中創建這些元素並插入並追加它們會更快嗎? 我不確定是否有很大的差異。所以,在這方面的任何幫助/建議將不勝感激。頁面速度優化:使用javascript與html寫入DOM

+0

恕我直言沒有那麼不同,在javascript中創建元素或在javascript中獲取HTML創建的元素在「資源」中可以花費多少錢? – MiPnamic 2011-03-23 16:57:58

回答

6

幾年前,我做了一個實驗。分配給元素的innerHTML屬性創建複雜結構要比使用重複的createElementappendChildinsertBefore等調用要快得多。我已經挖出了關於它的帖子(原型& script.aculo.us郵件列表);下面。

請記住,HTML解析和渲染它迅速什麼瀏覽器做,他們正在高度優化的做到這一點。如果您將一個包含複雜HTML結構的字符串分配給容器元素的屬性innerHTML,那麼您會使一個從JavaScript層跳到瀏覽器的呈現層,之後瀏覽器的分析和呈現代碼可以不間斷地繼續。相比之下,如果使用DOM API構建一些複雜的結構,不僅會出現大量的跨層傳輸(JavaScript - > browser - > JavaScript),而且瀏覽器還必須使用DOM API而不是其內部結構。因此,通常值得一看寫得很好的JavaScript模板引擎(如果你想做這個客戶端的話)。這些通常會將模板「編譯」成一個易於處理的形式,並且在處理特定數據集期間,他們將使用技巧,例如通過Array#push將字符串構建爲數組中的碎片,然後通過Array#join得到最終結果作爲分隔符傳入""。對於大字符串,它可以比字符串連接更快,但不同於innerHTML與DOM之間的不同,對於大的字符串來說,它可以比字符串連接更快,不過它的實現依賴於Firefox的SpiderMonkey與Chrome的V8還是IE的JScript。只是在多麼如何更快。

Here's the mailing list從幾年前我在談論消息(說基本上就是我上面說的,哇,那是兩年前),here's the Pastie它指的是,這裏是一個copied to JSBin,終於...這裏是代碼:(請注意,代碼是而不是打算永遠是一種美麗和快樂的事物,這是一個快速的黑客......儘管如此,我想我認爲我會破解一些東西現在更好,兩年後)。

這可能是值得將其轉換爲可在jsPerf上工作的東西。恐怕現在沒有時間去做那件事了。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html> 
<head> 
<style> 
#log { 
    border-bottom: 1px solid black; 
} 
#log p { 
    margin:  0; 
    padding: 0; 
} 
</style> 
<script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/prototype/1/prototype.js'></script> 
<script type='text/javascript'> 
document.observe('dom:loaded', function() { 
    $('btnDOMDirect').observe('click', useDOMDirect); 
    $('btnPrototypeDOM').observe('click', usePrototypeDOM); 
    $('btnHTML').observe('click', useHTML); 

}); 

var numRows = 10; 
var numCols = 10; 

function usePrototypeDOM(evt) 
{ 
    var table; 
    var tbody; 
    var tr; 
    var td; 
    var row; 
    var col; 
    var start; 
    var end; 

    start = (new Date()).getTime(); 

    table = new Element('table'); 
    tbody = new Element('tbody'); 
    table.appendChild(tbody); 
    for (row = 0; row < numRows; ++row) { 
     tr = new Element('tr'); 
     tbody.appendChild(tr); 
     for (col = 0; col < numCols; ++col) { 
      td = new Element('td'); 
      td.update('Row ' + row + ', col ' + col); 
      tr.appendChild(td); 
     } 
    } 
    $('targetTable').update(table); 

    end = (new Date()).getTime(); 
    log('DOM took ' + (end - start) + 'ms'); 
} 

function useDOMDirect(evt) 
{ 
    var table; 
    var tbody; 
    var tr; 
    var td; 
    var row; 
    var col; 
    var start; 
    var end; 

    if (Prototype.Browser.IE) { 
     alert("DOM direct doesn't work on IE because I used table elements. Sorry. The other two work."); 
     return; 
    } 

    start = (new Date()).getTime(); 

    table = document.createElement('table'); 
    tbody = document.createElement('tbody'); 
    table.appendChild(tbody); 
    for (row = 0; row < numRows; ++row) { 
     tr = document.createElement('tr'); 
     tbody.appendChild(tr); 
     for (col = 0; col < numCols; ++col) { 
      td = document.createElement('td'); 
      td.update('Row ' + row + ', col ' + col); 
      tr.appendChild(td); 
     } 
    } 
    $('targetTable').update(table); 

    end = (new Date()).getTime(); 
    log('DOM took ' + (end - start) + 'ms'); 
} 

function useHTML(evt) 
{ 
    var html; 
    var row; 
    var col; 
    var start; 
    var end; 

    start = (new Date()).getTime(); 

    html = '<table><tbody>'; 
    for (row = 0; row < numRows; ++row) { 
     html += '<tr>'; 
     for (col = 0; col < numCols; ++col) { 
      html += '<td>Row ' + row + ', col ' + col + '</td>'; 
     } 
     html += '</tr>'; 
    } 
    html += '</tbody></table>'; 
    $('targetTable').update(html); 

    end = (new Date()).getTime(); 
    log('HTML took ' + (end - start) + 'ms'); 
} 

function log(msg) 
{ 
    var l; 
    var p; 

    l = $('log'); 
    if (l) { 
     p = new Element('p'); 
     p.update(msg); 
     l.appendChild(p); 
    } 
} 
</script> 
</head> 
<body> 
<input type='button' id='btnDOMDirect' value='DOM Direct' /> 
<input type='button' id='btnPrototypeDOM' value='Prototype DOM' /> 
<input type='button' id='btnHTML' value='HTML' /> 
<div id='log'></div> 
<div id='targetTable'></div> 
</body> 
</html> 
+0

是的,如果沒有附加到容器元素內的任何元素的事件監聽器,使用'container.innerHTML =「」'而不是遞歸'container.removeElement'。這節省了很多時間。 – Lekensteyn 2011-03-23 17:00:20

0

它會一直比較慢,使用JavaScript來做到這一點,因爲它運行在頁面加載的頂部,而不是與它,因爲添加元素到HTML會。然而,你也可以說,沒有HTML中的元素,頁面的實際負載較少(儘管不是很顯着)。

另一點是,雖然JavaScript在垃圾收集方面相當糟糕,所以如果你正在做大量的DOM調用,它最終會增加你的處理能力。

另外還有,如果你有興趣維護一個語義網站,你需要標籤嗎?它沒有javascript的優雅降級?等等這取決於你想要採取的角度,我想。

0

如果你正在創建很多元素,innerHTML可以更快,但它不是官方DOM標準的一部分(雖然它被廣泛支持)。我的建議是爲頁面提供一個框架佈局,包括儘可能多的HTML,然後獲取頁面相關部分的引用,並使用標準DOM方法插入這些值。

這應該是相當快,將保持演示文稿和邏輯分離,並可能最終變得更靈活,在未來的網站更改或重新設計的情況下。

0

修改innerHTML而不是使用DOM方法。

根據Quirksmode上的這個benchmark of W3C DOM vs innerHTML,它看起來好像所有測試過的瀏覽器都是,而HTML的速度比DOM快得多