2012-03-08 80 views
28

我有很多元素,我的JS小部件需要創建並添加到DOM經常。他們從不改變。在JavaScript中創建大型靜態DOM元素的最佳方法是什麼?

所以一個選項是將HTML本身存儲爲JS字符串,並使用jQuery創建字符串中的元素,然後將其附加到文檔:

var elements = "<div><table><tr><td>1</td><td>2</td></tr></table></div>"; 
function create() { 
    return $(elements); 
} 
$("body").append(create()); 

另一種選擇是寫一個將使用使用document.createElement(「格」),或$(「<DIV>」)多次來構建元素,它們添加到對方那裏需要的功能,然後附加到文件:

function create() { 
    return $("<div>").append($("<table>")...... 
} 
$("body").append(create()); 

在第一種情況下,我有一個很大的JS字符串實際上是HTML。在第二種情況下,我有一個笨重的JS實際上代表了HTML。

其中一個或另一個有(dis)優點嗎?有沒有更好的解決方案,我沒有想到?

+1

這聽起來像一個JS模板引擎的作業,如http:// handlebarsjs .com/- 不幸的是,我不太瞭解它爲您提供真正的解決方案,但我認爲它可能有幫助。 – Nix 2012-03-08 09:01:20

+0

@Nix謝謝,一直在尋找一種方式來創建複雜的DOM元素,這種方式非常健全,易於維護。 handlebars.js正是我所需要的。 :) – DavidScherer 2014-04-11 19:45:18

回答

27

注意:如果你討厭閱讀,只是檢查總結下面的最終答案

也許你不需要創建那些幫助o f jQuery。

如果該html的結構複雜(因此使用document.createElement方法將是一個矯枉過正)我會去innerHTML屬性。

// somewhere in your code, preferably outside of global scope 
var div = document.createElement('div') 
div.id = 'mycustomdiv' 
document.getElementsByTagName('body')[0].appendChild(div); 
// assuming elements contains string of html with your elements 
div.innerHTML = elements; 

這樣你就避免了(假設再次)在jQuery對象中創建和包裝元素的不必要開銷。


更新:測試自己什麼是最快的方法http://jsperf.com/creating-complex-elements。這個測試證實,當你試圖壓縮性能的每一點時,都會恢復到香草javascript和經典的DOM操作。


更新2探討爲什麼在Firefox 10 innerHTML的方法有關於這樣糟糕的結果路過滿弦jQuery.append,我看了一下jQuery的來源。

事實證明(在jQuery 1.7.1中),他們通過利用document.createDocumentFragment(當然對於沒有適當支持的瀏覽器有一些回退)使用另一種創建dom元素的方法。

DocumentFragments是DOM節點。它們不是主DOM樹的一部分。通常的用例是創建文檔片段,將元素附加到文檔片段,然後將文檔片段追加到DOM樹中。在DOM樹中,文檔片段被其所有子項取代。

由於文檔片段在主DOM樹的記憶,而不是部分,附加兒童它不會導致頁面迴流

假設createDocumentFragment可用,它證明是跨腳本的整體跨瀏覽器性能的最佳方法。

所以,總結一下:

我認錯。 如果您在創建新DOM元素時在不同瀏覽器中尋找最佳性能,請關注文檔片段(如果您不想自己處理各種角落案例,請使用jQuery)。

對於有關的DocumentFragment檢查約翰Resig的博客這個職位的JS創建DOM的3種公共途徑和最好的辦法http://ejohn.org/blog/dom-documentfragments/

+0

+1爲摘要在最後。我認爲你應該大膽,只有這一點。 – styfle 2013-03-07 01:24:22

+0

@WTK,我認爲測試只會在每插入25次後清除孩子纔是公平的,因爲在達到最後一次測試時,DOM被嚴重污染,瀏覽器已經哭了。 – 2015-01-28 17:08:09

+0

也許像這樣http://jsperf.com/dquery-vs-jquery-inserting-dom-elements – 2015-01-28 17:08:43

2

您可以嘗試對靜態HTML塊進行AJAX提取,而不是將其存儲在頁面本身中。它可以讓你更靈活地在將來插入什麼類型的塊。

另外(這只是一個隨機的想法,並沒有很好地充實),您可以將「結構」存儲爲JSON數據,然後動態地解析它。可能類似{"div": {"div": {"span": "Text here"}}}<div><div><span>Text here</span></div></div>。儘管如此,我仍然會使用AJAX。 :)

+0

沒有想過將它存儲在服務器上......我想我可以爲它創建一個JSP片段並使用AJAX檢索它。嗯.. – 2012-03-08 08:56:28

1

如果你是因爲你調用$('<div>')或第二個每次找的表現我要堅持的第一個版本$('<table>')要創建一個新的jQuery對象,然後調用.append()這也另一種方法叫你怎麼做。
我會去第一個。

+0

但比讓JQuery解析一個巨大的字符串更快嗎?我想這可能也很貴... – 2012-03-08 08:58:11

+0

是的,我不確定,這取決於你想創建多少元素!但使用AJAX並不是一個好主意,因爲這會讓速度更慢。但是,爲什麼你在那個函數中返回一個jquery對象?返回字符串,它也將工作! – 2012-03-08 09:03:34

1

你已經回答了你自己。

編輯:刪除錯誤的樣本。

或者還有另一種選擇,你可以把HTML權到當前的HTML中隱藏的div像這樣:

<div id="hiddenContainer" style="display:none;"> 
    <div><table><tr><td>1</td><td>2</td></tr></table></div> 
</div> 

然後在jQuery的,你可以閱讀:

var elements = $("#hiddenContainer").html() 
+0

JS中沒有(適當的)多行字符串。 – Flo 2012-03-08 09:19:22

+0

@Flo你能詳細說明一下嗎?還是鏈接? – 2012-03-08 09:21:51

+0

http://jsfiddle.net/AzPvy/2/ – Flo 2012-03-08 09:33:01

22

詳細的分析更多的閱讀。

我公司將提供3種方式創建大型DOM和他們的優點和缺點,以及課程的大型DOM創建,爲什麼最優化的方式。 底線是在js中創建DOM時,原生JS和DOM方法是你的朋友,除非沒有其他方式(不太可能),否則不要使用jquery。

用於比較的測試數據:創建400行,5列並附加到DOM。 testData是您以json形式從後端獲取以創建表的對象的列表。

附加執行時間的測試結果快照不同瀏覽器的enter image description here HTML

<div id="employeeListContainer1"></div> 
<table id="employeeList2"> 
<thead> 
    <tr> 
     <th>First Name</th> 
     <th>Last Name</th> 
     <th>Title</th> 
     <th>ID</th> 
     <th>Department</th> 
    </tr> 
</thead> 

1路:字符串連接最優化的方式在不同瀏覽器的性能方面)

var tableElementContainer1 = document.getElementById("employeeListContainer1"), 
    temptableHolder = '<table><thead><tr><th>First Name</th><th>Last Name</th><th>Title</th><th>ID</th><th>Department</th></tr></thead><tbody>'; 
     for(var i=0,len=testData.length; i<len; i++){ 
       temptableHolder += '<tr><td>' + testData[i].firstName + '</td><td>' + testData[i].lastName + '</td><td>' + testData[i].title 
         + '</td><td>' + testData[i].id + '</td><td>' + testData[i].department + '</td></tr>'; 
      } 
    temptableHolder += '</tbody></table>'; 
    tableElementContainer1.innerHTML = temptableHolder ; 

優點: - 跨火狐/鉻/ IE/Safari瀏覽器最快執行時間(3到5毫秒跨瀏覽器)。通過performance.now()和console.time()API測量。

缺點: - 當列數更多,並且需要設置很多屬性時,使用字符串可能會變得困難並且不太主要。

第二個辦法:本地的js使用document.createElement()(這是在不同的瀏覽器性能方面第二好的辦法)

var tableBody = document.createElement('tbody'), 
tableElement2 = document.getElementById("employeeList2"), 
    for(var i=0,len=testData.length; i<len; i++){ 
      tableRow = document.createElement("tr"); 
      for(var k in testData[i]){ 
       rowCell = document.createElement("td"); 
       rowCell.appendChild(document.createTextNode(testData[i][k])); 
       tableRow.appendChild(rowCell); 
      } 
      tableBody.appendChild(tableRow); 
     } 
tableElement2.appendChild(tableBody); 

優點: - 跨火狐/ Chrome的第二最快的執行時間/ Safari (跨瀏覽器5到12毫秒)。通過performance.now()和console.time()API測量。 - 比第一次進場主要站得住腳

缺點: - 執行時間是多在IE瀏覽器,90+ millsec

第三屆方式:使用jQuery創建DOM(我的建議是不要「噸使用它)

var tableBody = $('<tbody></tbody>'), 
    tableElement2 = document.getElementById("employeeList2"), 
     for(var i=0,len=testData.length; i<len; i++){ 
      tableRow = $("<tr></tr>"); 
      for(var k in testData[i]){ 
       rowCell = $("<td></td>"); 
       rowCell.append(testData[i][k]); 
       tableRow.append(rowCell); 
      } 
      tableBody.append(tableRow); 
     } 
tableElement2.append(tableBody); 

優點: - 輕鬆的元素添加屬性/班/款式和易於閱讀和主要站不住腳。

缺點: - 在所有瀏覽器最差執行時間(220毫秒到330毫秒),最慢的數字是IE

相關問題