我有许多元素,我的一个JS小部件需要经常创建并添加到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”)或$(“&lt; div&gt;”)来构建元素,在需要的地方将它们附加到彼此,然后附加到文件:
function create() {
return $("<div>").append($("<table>")......
}
$("body").append(create());
在第一种情况下,我有一个很大的JS字符串,实际上是HTML。在第二种情况下,我有一个实际上代表HTML的笨重的JS。
是否有(dis)优势?有没有更好的解决方案我没想到?
答案 0 :(得分:29)
注意:如果您讨厌阅读,只需查看下面的摘要以获得最终答案
也许你真的不需要在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。这个测试证实,当你试图挤压每一个性能时,都会恢复到vanilla 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的更多阅读,请参阅John Resig博客http://ejohn.org/blog/dom-documentfragments/
上的这篇文章答案 1 :(得分:26)
详细分析了3种在JS中创建DOM的方法和最佳方法。
我将提供3种方法来创建大型DOM及其优缺点,当然也是大型DOM创建的最佳方式及其原因。 底线是在js中创建DOM时,原生JS和DOM方法是你的朋友,除非没有其他办法(不太可能),否则不要使用Jquery。
用于比较的测试数据:创建了包含5列的400行并附加到DOM。 testData是从json格式的后端获得的对象列表,用于创建表。
针对不同浏览器的附加执行时间测试结果快照 的 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>
第一种方式:字符串连接 (最优化的方式就浏览器的性能而言)
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 ;
优点: - 跨Firefox / Chrome / 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);
优点: - Firefox / Chrome / Safari (浏览器5到12毫秒)的第二快执行时间。通过performance.now()和console.time()API测量。 - 比第一种方法更主要的成功
缺点: - IE浏览器的执行时间更长, 90+毫秒
第三种方式:使用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 ms至330 ms),IE中最慢的数字
答案 2 :(得分:2)
您可以尝试对静态HTML块进行AJAX提取,而不是将其存储在页面本身中。它允许您更灵活地使用您希望将来插入的块类型。
或者(这只是一个随机的想法而且没有很好地充实),您可以将“结构”存储为JSON数据,然后动态解析它。 {"div": {"div": {"span": "Text here"}}}
可能类似于<div><div><span>Text here</span></div></div>
。我仍然会使用AJAX。 :)
答案 3 :(得分:1)
如果您正在寻找性能,我会坚持使用第一个版本,因为在第二个版本中,每当您调用$('<div>')
或$('<table>')
时,您正在创建一个新的jQuery对象,然后调用{{1}这也是另一种叫你的方法
我会选择第一个。
答案 4 :(得分:1)
你已经回答了自己。
编辑:删除错误的样本。
或者还有另一种选择,您可以将HTML直接放入隐藏div中的当前html中,如下所示:
<div id="hiddenContainer" style="display:none;">
<div><table><tr><td>1</td><td>2</td></tr></table></div>
</div>
然后在jquery中,你可以阅读它:
var elements = $("#hiddenContainer").html()