2012-03-08 65 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

相关问题