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

8fsztsew  于 9个月前  发布在  jQuery
关注(0)|答案(6)|浏览(122)

我有很多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. div Element(“div”)或$(““)来构建元素,在需要的地方将它们彼此追加,然后追加到文档中:

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


在第一种情况下,我有一个很大的JS字符串,它实际上是HTML。在第二种情况下,我有一个笨拙的JS片段,它实际上代表HTML。
这两种方法有什么优点或缺点吗?有没有我没有想到的更好的解决方案?

7z5jn7bk

7z5jn7bk1#

详细分析了JS中创建DOM的3种常见方法以及最佳方法。

我将提供3种创建大型DOM的方法及其优缺点,当然还有最优化的大型DOM创建方法及其原因。底线是,在js中创建DOM时,原生JS和DOM方法是你的朋友,不要使用Jquery,除非没有其他方法(这是不可能的)。

**对比测试数据:**创建了400行,5列,并追加到DOM中。testData是您从后端获取的json形式的对象列表,用于创建表。

随附不同浏览器的执行时间测试结果快照x1c 0d1xHTML

<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>
</table>

字符串

  • 第一种方式:字符串连接 *(跨浏览器性能最优化方式
var tableElementContainer1 = document.getElementById("employeeListContainer1");
var 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文档. js元素()*(就跨浏览器性能而言,这是第二种最佳方法)
var tableBody = document.createElement('tbody');
var 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>');
var 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
2lpgd968

2lpgd9682#

  • 注意:如果你讨厌阅读,只需检查总结下面的最终答案 *

也许你真的不需要在jQuery的帮助下创建这些。
如果html的结构很复杂(因此使用document.xml元素的方法是一种矫枉过正),我会使用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对象中创建和 Package 元素的不必要开销。
更新:测试你自己最快的方法是什么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树的一部分,因此向其追加子级不会导致页面重排
假设可以使用XML DocumentFragment,就脚本的整体跨浏览器性能而言,它是最好的方法。
所以,总结一下:

**如果你在创建新的DOM元素时,希望在不同的浏览器中获得最佳性能,请关注文档片段(如果你不想自己处理各种极端情况,请使用jQuery)。

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

ncecgwcz

ncecgwcz3#

你可以尝试用AJAX获取静态HTML块,而不是将其存储在页面本身中,这样你就可以更灵活地选择将来要插入的块。
或者(这只是一个随机的想法,并没有很好地充实出来),你可以将“结构”存储为JSON数据,然后动态地解析它。可能是像{"div": {"div": {"span": "Text here"}}} for <div><div><span>Text here</span></div></div>这样的东西。我仍然会使用AJAX。:)

5ktev3wc

5ktev3wc4#

这个问题很久很久以前就被问到了。对于现代浏览器来说,在元素上使用innerHtml属性是最有效的方法。

// Either create a new element or select an existing one:
const el = document.querySelector('#app');

el.innerHTML = `
<ul>
  <li>Lorem ipsum dolor sit amet.</li>
  <li>Adipisci perspiciatis blanditiis recusandae praesentium!</li>
  <li>Libero, culpa similique. Laborum, tempore!</li>
  <li>Nobis ab tempora laboriosam laborum!</li>
  <li>Distinctio, a? Maiores, pariatur nihil.</li>
  <li>Ab vitae quibusdam tempore rem?</li>
  <li>Delectus veritatis exercitationem rem ipsam.</li>
  <li>Eveniet praesentium quasi provident dicta!</li>
  <li>Quae quis consequuntur perspiciatis omnis.</li>
  <li>Delectus similique doloribus consequatur quidem!</li>
</ul>
`;

字符串
浏览器将创建元素。它比通过迭代单独创建元素更快,更干净。您可以添加属性,事件等。

mfpqipee

mfpqipee5#

还有另一种选择,你可以把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()

qrjkbowd

qrjkbowd6#

如果你追求的是性能,我会坚持使用第一个版本,因为在第二个版本中,每次调用$('<div>')$('<table>')时,你都在创建一个新的jQuery对象,然后调用.append(),这也是你调用的另一个方法。
我会选第一个。

相关问题