在JavaScript中创建大型静态DOM元素的最佳方法?

Ton*_*y R 31 html javascript jquery dom

我有许多元素,我的一个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());
Run Code Online (Sandbox Code Playgroud)

另一种选择是编写一个函数,它将多次使用document.createElement("div")或$("<div>")来构建元素,在需要的地方将它们相互附加,然后附加到文档:

function create() {
  return $("<div>").append($("<table>")......
}
$("body").append(create());
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,我有一个很大的JS字符串,实际上是HTML.在第二种情况下,我有一个实际上代表HTML的笨重的JS.

一个或另一个有(dis)优势吗?有没有更好的解决方案我没想到?

WTK*_*WTK 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;
Run Code Online (Sandbox Code Playgroud)

这样你就可以避免(假设再次)在jQuery对象中创建和包装元素的不必要的开销.


更新:自己测试什么是最快的方法http://jsperf.com/creating-complex-elements.这个测试证实,当你试图挤压每一个性能时,恢复为vanilla javascript和经典DOM操作.


更新2.为了研究为什么Firefox 10上的innerHTML方法在将完整字符串传递给jQuery.append方面有如此糟糕的结果,我看了一下jQuery源代码.

事实证明(在jQuery 1.7.1中),他们使用另一种创建dom元素的方法是利用document.createDocumentFragment(当然对于没有适当支持的浏览器有一些后备).

DocumentFragments是DOM节点.它们永远不是主DOM树的一部分.通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树.在DOM树中,文档片段由其所有子项替换.

由于文档片段在内存中而不是主DOM树的一部分,因此将子项附加到它不会导致页面重排.

假设createDocumentFragment可用,那么就脚本的整体跨浏览器性能而言,它是最好的方法.

所以,总结一下:

我纠正了.如果您在创建新DOM元素时在不同浏览器中寻找最佳性能,请关注文档片段(如果您不想自己处理各种角落案例,请使用jQuery).

有关documentFragment的更多阅读,请参阅John Resig博客http://ejohn.org/blog/dom-documentfragments/上的这篇文章.


San*_*eev 26

详细分析了3种在JS中创建DOM的方法和最佳方法.

我将提供3种方法来创建大型DOM及其优缺点,当然也是大型DOM创建的最佳方式及其原因.底线是在js中创建DOM时,本机JS和DOM方法是你的朋友,除非没有其他方法(不太可能),否则不要使用Jquery.

用于比较的测试数据:创建400行,包含5列并附加到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>
Run Code Online (Sandbox Code Playgroud)

第一种方式:字符串连接(跨浏览器的性能最佳方式)

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 ;
Run Code Online (Sandbox Code Playgroud)

优点: - 跨Firefox/Chrome/IE/Safari最快的执行时间(跨浏览器3到5毫秒).通过performance.now()和console.time()API测量.

缺点: - 当列数更多并且您需要设置大量属性时,使用字符串可能会变得很困难并且不太可能.

第二种方式:Native 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);
Run Code Online (Sandbox Code Playgroud)

优点: - 跨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);
Run Code Online (Sandbox Code Playgroud)

优点: - 易于在元素上添加属性/类/样式,易于阅读和主要成功.

缺点: - 所有浏览器的执行时间最短(220毫秒到330毫秒),IE中最慢的数字