好的,我正在重写当前项目中的一些vanilla JS函数,而且我正处于为工具提示等生成大量HTML的地方。
我的问题是,这样做是否更好/更受欢迎:
var html = '<div><span>Some More Stuff</span></div>';
if (someCondition) {
html += '<div>Some Conditional Content</div>';
}
$('#parent').append(html);
OR
var html = $('<div/>').append($('<span/>').append('Some More Stuff'));
if (someCondition) {
html.append($('<div/>').append('Some conditionalContent');
}
$('#parent').append(html);
答案 0 :(得分:36)
从绩效角度来看:取决于。
在你的简短示例中,附加文本会更快,因为实际上直到最后才创建任何DOM元素。但是,如果你这样做 lot ,那么字符串连接的增加时间与缓存文档片段的性能相加就会增加。
执行$(html)
jQuery将其缓存为document fragment(假设字符串为512字节或更少),但如果只缓存$("<div />")
则没有太多收益。 。但是,如果你这样做了数千次,就会产生可衡量的影响,因为字符串连接变得更加昂贵,因为你的字符串越来越长,缓存的文档片段成本相当稳定。
更新:以下是一些快速示例,了解我的意思,使用firebug来获取控制台时间:
您可以自行运行:http://jsfiddle.net/Ps5ja/
console.time('concat');
var html = "";
for(var i = 0; i < 500; i++) {
html += '<div><span>Some More Stuff</span></div>';
html += '<div>Some Conditional Content</div>';
}
var elem = $(html);
console.timeEnd('concat'); //25ms
console.time('DOM');
var parent = $("<div />")
for(var j = 0; j < 500; j++) {
parent.append($('<div/>').append($('<span/>', {text :'Some More Stuff'})));
parent.append($('<div/>',{ text: 'Some conditionalContent' }));
}
console.timeEnd('DOM'); //149ms
console.time('concat caching');
var html = "";
for(var i = 0; i < 5000; i++)
html += '<div><span>Some More Stuff</span></div><div>Some Conditional Content</div>';
var elem = $(html);
console.timeEnd('concat caching'); //282ms
console.time('DOM caching');
var parent = $("<div />")
for(var j = 0; j < 5000; j++)
parent.append('<div><span>Some More Stuff</span></div><div>Some Conditional Content</div>');
console.timeEnd('DOM caching'); //157ms
注意:字符串测试中的var elem = $(html);
是这样我们最终创建相同的DOM元素,否则你将字符串连接与实际的DOM创建进行比较,几乎不公平比较,并且没有真正有用要么:)
您可以通过上面的内容看到,由于缓存片段更复杂,缓存越多,影响越大。在第一个测试中,这是没有条件清理的示例,DOM会丢失,因为在此测试中有很多小的操作(在我的机器上,但你的比率应该大致相同): HTML联系人:25毫秒, DOM操作:149毫秒。
但是,如果您可以缓存复杂片段,那么您将获得不重复创建这些DOM元素的好处,只需克隆它们即可。在第二个测试中,DOM胜出,因为虽然HTML方法创建的DOM元素集合 5000次,但第二个缓存方法只创建一次,并将其克隆5000次。在此测试中: HTML Concat:282ms , DOM操作:157ms 。
我意识到这不是直接以回应你的问题,但基于评论似乎对性能有一些好奇心,所以只要给出你可以看到/测试/玩的东西。
答案 1 :(得分:5)
我已经测试了Nick Craver提交的代码,并且发现只有当元素的内容没有改变时,DOM缓存的工作速度才会更快 。但是,如果您在for循环的每次迭代中更改字符串,则速度会急剧下降。
这是相同的代码修改(在小提琴上测试:http://jsfiddle.net/Ps5ja/42/)
console.time('concat');
var html = "";
for(var i = 0; i < 500; i++) {
html += '<div><span>Some More Stuff</span></div>';
html += '<div>Some Conditional Content</div>';
}
var elem = $(html);
console.timeEnd('concat');
console.time('DOM');
var parent = $("<div />")
for(var j = 0; j < 500; j++) {
parent.append($('<div/>').append($('<span/>', {text :'Some More Stuff'})));
parent.append($('<div/>',{ text: 'Some conditionalContent' }));
}
console.timeEnd('DOM');
console.time('concat caching');
var html = "";
for(var i = 0; i < 10000; i++)
html += '<div><span>Some More Stuff</span></div><div>Some Conditional Content'+i+'</div>';
var elem = $(html);
console.timeEnd('concat caching');
console.time('concat array.join');
var arr = [];
for(i = 0; i < 10000; i++)
arr.push('<div><span>Some More Stuff</span></div><div>Some Conditional Content'+i+'</div>');
var elem = $(arr.join(''));
console.timeEnd('concat array.join');
console.time('DOM caching - NO modification');
var parent = $("<div />")
// here the contained text is unchanged in each iteration
for(var j = 0; j <10000; j++)
parent.append('<div><span>Some More Stuff</span></div><div>Some Conditional Content</div>');
console.timeEnd('DOM caching - NO modification');
console.time('DOM caching with modification');
var parent = $("<div />")
// here the contained text is modified in each iteration
// (the value od J is appended to the text)
for(var j = 0; j <10000; j++)
parent.append('<div><span>Some More Stuff</span></div><div>Some Conditional Content'+j+'</div>');
console.timeEnd('DOM caching with modification');
结论是,只有当您计划反复复制相同的HTML片段时,DOM缓存才能更快地运行。如果没有使用字符串连接。
我在使用Array.join方法时没有发现任何速度优势。但是我没有彻底测试过(如果迭代次数更多,可能会发生变化)。
答案 2 :(得分:2)
赞成对innerHTML方法的DOM操作。首先,DOM操作将正确处理需要使用innerHTML进行转义的字符。另一方面,它通常更快,有时很多更快。
答案 3 :(得分:0)
一般情况下,如果我要生成很多html,我会将其全部收集在一个字符串中,让浏览器一次性生成所有元素。
如果涉及到大量的条件或循环,那么您可能希望使用Array.join()而不是使用+的字符串连接。使用字符串连接,浏览器将生成许多中间字符串,这可能非常慢; Array.join()跳过所有这些中间字符串。对于这些情况,我会做类似的事情:
var html = ['<div><span>Some More Stuff</span></div>'];
for (var i = 0; i < 1000; i++) {
html.push('<div>Some Loop Content</div>');
}
$('#parent').append(html.join(''));