使用 jQuery 创建新元素的正确或更好方法是什么?

Which is the correct or better way to create a new element with jQuery?

相关答案 cleate an element 更好用

$("<div>", {id: "foo", class: "a"});

$("<div />", {id: "foo", class: "a"});

它们都有效,但使用哪个更好或更正确?

官方API Documentation说为了保证跨平台兼容性,snippet必须格式正确。可以包含其他元素的标签应与结束标签配对:

$( "<a href='http://jquery.com'></a>" );

while 不能包含元素的标签可能快速关闭或不快速关闭:

$( "<img>" );
$( "<input>" );

所以,最后使用前两个选项之一作为 div?

是错误的

如果您仅通过易于衡量的指标来衡量:第一个更好,因为它短了 2 个字节。

一旦您开始考虑可读性和其他不太具体的考虑因素,这在很大程度上就变成了一个见仁见智的问题。

So, at the end it's wrong to use one of the first two options for a div?

不,该部分仅适用 "If the HTML is more complex than a single tag without attributes"

来自 jQuery 的网站:

It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler..

注意它没有提到 HTML 代

JavaScript 提供了 document.createElement 方法。如果 HTML-like 字符串作为选择器传递,jQuery 将使用此方法。

jQuery 入口点 ($(whatEverIFeelLikeDoingToday)) 类型检查字符串、节点或函数的选择器,然后相应地处理请求。如果参数是字符串,那么它会经过 +/- 60 行代码(我是 HTML 吗?我是选择器吗?我是 ID 吗?我是 class 吗?)。在识别出类似 HTML 的字符串后,它会被传递给另一个函数(附加函数调用)以生成 - 因此速度很慢(请参见下面的基准测试)。事实上,除了一致性之外,它并没有给流程增加太多价值,只是减慢了速度。

我发现最好的做法是:不使用 jQuery 来完成相当简单的任务(即节点创建)-无论在哪里练习,都要消除障碍。

var div = document.createElement('div');
div.setAttribute("id", "foo");
div.setAttribute("class", "a");
div = $(div);

请注意此 benchmark. (Just about 4x faster in Chrome). This solution is Faster than the two described above and inherently Cross platform 中的显着性能提升。

我认为更少字节与更快执行时间的争论不在该线程的范围内。但是,假设您正在缩小代码,我将抛出一个循环遍历数组以为 table 生成 html 行的实际示例。字节不是问题,您只需要加载一次脚本 - 执行会让您陷入困境。

在您的情况下更好或正确地使用它取决于此代码在您的页面中出现的频率。 @Quentin 是正确的,因为第一个选项和第二个选项之间只有两个字节的差异。现在,如果代码只在整个页面中出现几次,那么实际上除非您在服务器上记录大量流量,否则您将看不到两者之间的显着差异,另一方面,如果您 运行一个中等到高流量的站点,或者将有大量此 javascript 的实例出现在您的页面上,那么最好的选择是选择选项一,因为它小两个字节并且在一个较大的页面上有很多使用此代码的实例,您会发现页面的字节大小有明显的节省。

至于格式良好的跨平台兼容性标签,第一个和第二个选项将在浏览器中产生完全相同的最终结果,因此在您的用例中,兼容性不会受到任何一个选项的影响。

基于这些观点,我建议使用选项一,因为它比选项二提供两个字节的优势,这实际上是您的用例中两个选项之间的唯一区别。

查看 jQuery 库,以下是 v2.2.0 line 2827 的相关部分。

init = jQuery.fn.init = function(selector, context, root) {
    var match, elem;

    // HANDLE: $(""), $(null), $(undefined), $(false)
    if (!selector) {
      return this;
    }

    // Method init() accepts an alternate rootjQuery
    // so migrate can support jQuery.sub (gh-2101)
    root = root || rootjQuery;

    // Handle HTML strings
    if (typeof selector === "string") {
      if (selector[0] === "<" &&
        selector[selector.length - 1] === ">" &&
        selector.length >= 3) {

        // Assume that strings that start and end with <> are HTML and skip the regex check
        match = [null, selector, null];

      } else {
        match = rquickExpr.exec(selector);
      }

      // Match html or make sure no context is specified for #id
      if (match && (match[1] || !context)) {

        // HANDLE: $(html) -> $(array)
        if (match[1]) {
          context = context instanceof jQuery ? context[0] : context;

          // Option to run scripts is true for back-compat
          // Intentionally let the error be thrown if parseHTML is not present
          jQuery.merge(this, jQuery.parseHTML(
            match[1],
            context && context.nodeType ? context.ownerDocument || context : document,
            true
          ));

          // HANDLE: $(html, props)
          if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
            for (match in context) {

              // Properties of context are called as methods if possible
              if (jQuery.isFunction(this[match])) {
                this[match](context[match]);

                // ...and otherwise set as attributes
              } else {
                this.attr(match, context[match]);
              }
            }
          }

          return this;

您将看到它检查选择器是否为 string,如果是,则查看它是否以 < 开头并以 > 结束。

if (typeof selector === "string") {
  if (selector[0] === "<" &&
    selector[selector.length - 1] === ">" &&
    selector.length >= 3) {

然后,考虑到正则表达式 rsingleTag 是:-

var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/>|)$/ );

匹配 "<div>""<div />",returning div as group[1].

parseHTML 将其用于 return 一个 div 元素,在 merge:-

jQuery.parseHTML = function( data, context, keepScripts ) {

    ...

    var parsed = rsingleTag.exec( data );

    // Single tag
    if ( parsed ) {
        return [ context.createElement( parsed[ 1 ] ) ];
    }

然后再次使用正则表达式,context 作为设置属性的对象:-

// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {

for 在每个 属性 设置上 this.attr(match, context[match]);

So, at the end it's wrong to use one of the first two options for a div?

如上所示,个人喜好。两者的工作原理相同。