【问题标题】:Which is better: string html generation or jquery DOM element creation?哪个更好:字符串 html 生成或 jquery DOM 元素创建?
【发布时间】:2011-02-11 00:46:43
【问题描述】:

好的,我正在我当前的项目中重写一些 vanilla JS 函数,并且我正处于为工具提示等生成大量 HTML 的地步。

我的问题是,这样做更好/更喜欢这样做:

var html = '<div><span>Some More Stuff</span></div>';
if (someCondition) {
    html += '<div>Some Conditional Content</div>';
}
$('#parent').append(html);

var html = $('<div/>').append($('<span/>').append('Some More Stuff'));
if (someCondition) {
    html.append($('<div/>').append('Some conditionalContent');
}
$('#parent').append(html);

?

【问题讨论】:

    标签: jquery dom-manipulation


    【解决方案1】:

    从性能的角度来看:这取决于

    在您的简短示例中,附加文本更快,因为您实际上直到最后才创建任何 DOM 元素。但是,如果您这样做很多,则字符串连接所增加的时间与缓存文档片段的性能相加。

    当您执行 $(html) 时,jQuery 会将其缓存为 document fragment(前提是该字符串为 512 字节或更少),但如果您仅缓存 $("&lt;div /&gt;") 并没有太大收益...但是如果您是这样做数千次,就会产生可衡量的影响,因为字符串连接会随着字符串变长而变得更昂贵,缓存文档片段的成本相当稳定。

    更新:这里有一些简单的例子来理解我的意思,在这里使用 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 创建进行比较,这几乎不是公平的比较,也不是真正有用的: )

    从上面可以看出,缓存的fragment越复杂,缓存的影响越大。在第一个测试中,这是你的例子,没有清理一下条件,DOM 丢失,因为有很多小操作正在进行,在这个测试中(在我的机器上,但你的比率应该大致相同): HTML 联系人:25 毫秒DOM 操作:149 毫秒

    但是,如果您可以缓存复杂的片段,您就不必重复创建这些 DOM 元素,只需克隆它们即可。在第二个测试中,DOM 胜出,因为虽然 HTML 方法创建了 DOM 元素集合 5000 次,但第二个缓存方法只创建了 一次,并克隆了 5000 次。在这个测试中:HTML Concat:282msDOM Manipulation:157ms

    我意识到这不是直接回答您的问题,但基于 cmets 似乎对性能有些好奇,所以只是提供一些您可以看到/测试/玩的东西。 p>

    【讨论】:

    • 很想知道为什么对此投反对票。男人是不是错了?启发我们。
    • 同意:为什么不赞成,对我来说似乎很合理。我没有做成千上万的连接,所以我认为没问题。顺便说一句,据我所知,firefox 和 chrome 现在都使用 StringBuilder 样式的字符串连接数组方法,因此字符串连接可以非常快。
    • 我只能猜测反对者可能认为这是过早的优化?
    【解决方案2】:

    支持 DOM 操作优于 innerHTML 方法。一方面,DOM 操作将正确处理需要使用 innerHTML 转义的字符。另一方面,它通常更快,有时快得多

    【讨论】:

    • 在这两个示例中我都没有使用 innerHTML:这是在讨论从头开始生成而不是直接操作现有元素。这几乎只是字符串连接与元素创建。
    • @EdWoodcock $("&lt;div&gt;1 2 3&lt;/div&gt;") 使用 innerHTML in implementation so yes you are using innerHTML`。
    • 不知道,有用的信息,但我将第二个示例中的 div 初始化为空白(据我所知不会使用 innerHTML?),并且在第一个示例,我从头开始构建一个字符串,然后使用 append(我假设它是 innerHTML,但只有一次)。
    • PPK 的测试表明,innerHTML 比 DOM 操作更快(对于 IE 来说快得多):quirksmode.org/dom/innerhtml.html
    【解决方案3】:

    一般来说,如果我有很多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(''));
    

    【讨论】:

    • 正如我之前所说,FF 以及据我所知 Chrome 和 Opera 会自动为字符串连接执行此方法,并且在 FF += 中实际上比数组方法更快。跨度>
    • 我猜你的项目不支持 IE?
    【解决方案4】:

    我测试了 Nick Craver 提交的代码,发现 DOM 缓存只有在元素内容不变的情况下才能更快。但是,如果您在 for 循环的每次迭代中更改字符串,速度会急剧下降

    这里修改了相同的代码(在 Fiddle 上测试它: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 方法的速度优势。但是我还没有彻底测试过(如果迭代次数更大,可能会发生变化)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-04
      • 1970-01-01
      • 2016-05-26
      • 2018-09-19
      相关资源
      最近更新 更多