使用jQuery创建HTML元素的最高效方法是什么?

434

最近我一直在做很多模态窗口弹出框等功能,我使用了jQuery。我用来创建页面上新元素的方法主要是:

$("<div></div>");

然而,我感觉这不是最好或最有效的创建元素的方式。从性能的角度来看,使用jQuery创建元素的最佳方式是什么?

这个答案提供了下面建议的基准测试。


1
尝试去除样式并查看是否可以加快速度。我发现在大型页面上,CSS 应用和更新会使事情变得最慢。 - CVertex
3
要注意避免过早地进行优化——如果你每次只处理几百个DOM元素或使用非常古老的浏览器,那么你可能不会注意到浏览器性能上的任何差异。 - Blazemonger
1
@Blazemonger,我并不是真的需要一种更有效率的创建DOM元素的方法,但是我所处的情境让我思考其他替代方案以及它们的效率。 - Darko
2
jQuery是一个库 - 几乎总会因为这个原因产生开销性能成本:就像通过口译与某人交谈。除非你想使用原始的JavaScript,否则利用写$('<div>')的速度并承担性能损失。 - Danny Bullis
1
http://jsben.ch/#/bgvCV <= 这个基准测试 应该能回答你的问题。 - EscapeNetscape
显示剩余4条评论
12个回答

311
我使用$(document.createElement('div'));基准测试显示,这种技术是最快的。 我猜测这是因为jQuery不必将其识别为元素并自行创建元素。
您应该使用不同的JavaScript引擎进行基准测试,并根据结果考虑受众群体。 从那里做出决定。

17
jQuery会将它附加到DOM中,但是放在哪里呢?这对我来说不太合理 —— 这个div会放在哪里呢? - strager
29
在 jQuery 中创建的 div 的添加方式与 JavaScript 相同。$('<div>') 本身不会附加到 DOM,直到您将其使用 append() 方法附加到某个元素上。 - Owen
6
@David - 显然你是对的。我想指出我大约两年前刚开始学习jQuery时添加了这个评论。你需要执行一个 appendTo,... 因为这些评论显然是错误的,所以我已经将它们删除了。 - tvanfosson
17
基准参考很好,但这也测试了创建数万个元素的过程。在典型情况下,你什么时候会处理那么多元素呢?很可能,你有更重要的事情要担心,而不是如何创建一个元素。document.createElement“运行了39,682次,用时0.097秒”,而$('<div>')“运行了12,642次,用时0.068秒”。我想说,如果某件事可以在不到一秒的时间内运行数千次,你就放心吧。 - Danny Bullis
21
此外,使用$(document.createElement('div'))可能不太高效,因为如果您只是偶尔创建一个元素,为此编写代码时间较长,而在浏览器中获得的好处却微乎其微。从技术上讲,由于查询成本和使用它时产生的开销,jQuery本身作为库可能不太高效。如果有人如此追求节省千分之一毫秒的时间,而要使用document.createElement而不是$('<div>'),那么他们不应该使用jQuery:因为$('<div>')正是你使用jQuery的原因之一! - Danny Bullis
显示剩余10条评论

166

个人建议(为了可读性):

$('<div>');

到目前为止,一些有关建议的数字(safari 3.2.1 / mac os x):

var it = 50000;

var start = new Date().getTime();
for (i = 0; i < it; ++i)  {
  // test creation of an element 
  // see below statements
}
var end = new Date().getTime();
alert( end - start );                

var e = $( document.createElement('div') );  // ~300ms
var e = $('<div>');                          // ~3100ms
var e = $('<div></div>');                    // ~3200ms
var e = $('<div/>');                         // ~3500ms              

16
从jQuery文档中:'当创建单个元素时,请使用闭合标签或XHTML格式。例如,要创建一个span,请使用$("<span/>")或$("<span></span>"),而不是没有闭合斜杠/标记。' - tvanfosson
7
@Owen,那种行为是一个 bug,而不是一个特性。垃圾进,垃圾出——恰好得到的垃圾是可以接受的。不过,在 jQuery 版本之间不要依赖它,除非函数规范发生了变化。 - strager
2
正如预期的那样,在Mac OS X Chrome(createElement()100ms vs.文本解析500ms)和Mac OS X Firefox(350ms vs. 1000ms)中看到类似的数字。感谢编写测试循环。 - Annika Backstrom
3
显然这一点已经有所改变,在当前文档中,它说:“当参数只有一个标签(可选的闭合标签或快速闭合标签)- $(“<img />”)或$(“<img>”),$(“<a></a>”)或$(“<a>”) - jQuery使用本地JavaScript createElement()函数创建元素。” - metatron
3
@MarcStober 没有冒犯之意。它仍然在这里:http://api.jquery.com/jQuery/#jQuery2。文档提到了“可选的闭合标签或快速关闭”。 - metatron
显示剩余2条评论

156

问题:

使用jQuery创建HTML元素的最有效方法是什么?

答案:

既然涉及到jQuery,那么我认为最好使用这种(简洁)方法(您正在使用)。

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'text':'Text Only',
}).on('click', function(){
    alert(this.id); // myDiv
}).appendTo('body');

演示.

这样,您甚至可以使用特定元素的事件处理程序,例如

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'style':'cursor:pointer;font-weight:bold;',
    'html':'<span>For HTML</span>',
    'click':function(){ alert(this.id) },
    'mouseenter':function(){ $(this).css('color', 'red'); },
    'mouseleave':function(){ $(this).css('color', 'black'); }
}).appendTo('body');

演示.

但是当你处理大量动态元素时,应该避免在特定元素中添加事件处理程序,而应该使用委托事件处理程序,例如

$(document).on('click', '.myClass', function(){
    alert(this.innerHTML);
});

var i=1;
for(;i<=200;i++){
    $('<div/>', {
        'class':'myClass',
        'html':'<span>Element'+i+'</span>'
    }).appendTo('body');
}

演示.

如果您创建并附加了数百个具有相同类别的元素,即 (myClass),那么事件处理将占用更少的内存,因为只有一个处理程序来为所有动态插入的元素执行任务。

更新:由于我们可以使用以下方法创建动态元素

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    'size': '30'
}).appendTo("body");

但是使用 jQuery-1.8.0 或更高版本,无法使用此方法设置 size 属性,并且这里有一个旧的错误报告,请看使用 jQuery-1.7.2此示例,它显示使用上述示例将 size 属性设置为 30,但是使用相同的方法,我们无法使用 jQuery-1.8.3 设置 size 属性,这里是一个不起作用的 fiddle。因此,要设置 size 属性,我们可以使用以下方法。
$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    attr: { size: "30" }
}).appendTo("body");

或者这一个

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    prop: { size: "30" }
}).appendTo("body");

我们可以将attr/prop作为子对象传递,但它仅适用于jQuery-1.8.0及更高版本。请参考此示例。但是,在jQuery-1.7.2或更早版本中(未在所有早期版本中进行测试),这种方法不起作用

顺便说一下,这来自于jQuery的错误报告。

有几种解决方案。首先是根本不使用它,因为它并没有节省任何空间,而且这会提高代码的清晰度:

他们建议使用以下方法(在早期版本中也可以使用,已在1.6.4中进行了测试)。

$('<input/>')
.attr( { type:'text', size:50, autofocus:1 } )
.val("Some text").appendTo("body");

因此,在我看来,最好使用这种方法。在阅读/发现这个答案之后,我进行了更新,并且该答案表明,如果您使用'Size'(大写S)而不是'size',那么它将会正常工作,即使在version-2.0.2中也是如此。

$('<input>', {
    'type' : 'text',
    'Size' : '50', // size won't work
    'autofocus' : 'true'
}).appendTo('body');

同时阅读有关prop的内容,因为在不同版本中存在差异,属性 vs. 属性


这是什么语法:$('<div/>', {.........})?我找了一些类似使用 $('<div>).attr({......}) 的内容。 - Rafael Ruiz Tabares
@RafaelRuizTabares,在 $('<div>', {...}) 中,您正在传递一个包含所有属性的对象,并且在 $('<div>').attr({...}) 中,您正在创建一个没有任何属性的元素,但稍后使用 attr() 方法设置属性。 - The Alpha
@TheAlpha,我在哪里可以找到关于我可以在{}中编写什么的信息?因为我看到它们是属性和事件,但对于<div>,您也使用html。谢谢! - Rafael Ruiz Tabares
在RafaelRuizTabares的建议下,搜索jQuery.com网站可能会有所帮助,或者使用谷歌进行搜索 :-) - The Alpha
2
这绝对是最干净、最易读的方式!可能不是最快的方式,但肯定比字符串拼接更少出错。感谢@TheAlpha。 - Ares

37

实际上,如果你使用 $('<div>'),jQuery 也会使用 document.createElement()

你可以在 第117行 看到这个过程。

虽然存在一些函数调用的开销,但除非性能至关重要(你需要创建数百[千]个元素),否则没有太多理由回到纯粹的 DOM

对于创建一个新网页中的元素,最好还是坚持使用 jQuery 的方式。


20

这不是正确的问题答案,但我仍然想分享一下...

如果你想动态创建大量元素并将其附加到DOM上,只需使用document.createElement('div')而跳过JQuery,可以显著提高性能。


20
如果你有很多HTML内容(不仅仅是一个div),你可以考虑将HTML构建到隐藏的容器中,然后在需要时更新并使其可见。这样,浏览器可以预解析大部分标记,并在调用时避免被JavaScript拖慢。希望这能帮到你!

谢谢您的建议。我以前使用过这种方法,但在这种特定情况下,我特别想了解如何创建元素。 - Darko

16

我认为你正在使用最佳方法,不过你可以对其进行优化:

 $("<div/>");

10

从 CPU 的角度来看,你不需要对一个极少执行的操作进行原始性能优化。


取决于你做这件事的频率。 - Rich Bradshaw
8
OP正在创建一个模态弹窗。这个操作不会每秒重复数千次,最多每几秒钟重复一次。使用 jQuery(html :: String) 方法完全没问题。除非情况极其不寻常,否则人们很难获得更好的“感知”性能。将优化精力花在需要优化的情况上。此外,jQuery在许多方面都进行了速度优化。使用它做明智的事情,并相信并验证它的速度快。 - yfeldblum

9
您需要理解,在使用jQuery的情况下,元素创建性能的重要性是无关紧要的。
请记住,除非您真正使用它,否则创建元素没有实际意义。
您可能会尝试测试 $(document.createElement('div'))$('<div>') 的性能差异,并从使用 $(document.createElement('div'))中获得更好的性能收益,但这只是还没有在DOM中的一个元素。
然而,在一天的结束时,您仍需要使用该元素,因此真正的测试应该包括像 .appendTo() 这样的其他操作。
让我们看看以下两个元素之间的比较:
var e = $(document.createElement('div')).appendTo('#target');
var e = $('<div>').appendTo('#target');
var e = $('<div></div>').appendTo('#target');
var e = $('<div/>').appendTo('#target');

你会注意到结果会有所不同。有时一种方法比另一种方法表现更好。这只是因为你电脑上的后台任务数量随时间而变化。 在这里测试 因此,归根结底,你想选择创建元素最小和最可读的方式。这样,至少你的脚本文件将尽可能小。在性能方面,这可能比在使用DOM之前创建元素的方式更重要。

我知道这很老,但在第一个示例中不需要jQuery: document.getElementById('target).appendChild(document.createElement('div')); - hisdrewness

8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接