【问题标题】:Which is the correct or better way to create a new element with jQuery?哪个是使用 jQuery 创建新元素的正确或更好的方法?
【发布时间】:2016-05-26 13:55:32
【问题描述】:

与答案https://stackoverflow.com/a/10619477/1076753相关的cate an element 比较好用

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

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

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

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

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

虽然不能包含元素的标签可能会被快速关闭:

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

那么,最后将前两个选项之一用于 div 是错误的吗?

【问题讨论】:

  • 编码太难了,以至于不必要地依赖浏览器恢复技术来处理 HTML 标签汤。只需始终使用有效的 HTML 来提供它,就可以免去将来的麻烦。
  • @ÁlvaroGonzález — &lt;div&gt;&lt;div /&gt; 都不是有效的 HTML(自闭合标记语法是 XML 功能而不是 HTML 功能,&lt;div&gt; 具有强制结束标记)。
  • @Quentin,这就是为什么我在问题标签中也写了 xhtml。
  • 对不起@charlietfl 但我在api.jquery.com/jquery上看不到这样的东西
  • 我已经阅读了所有的 cmets,我想知道为什么没有人解释更好的方法是 $("&lt;div&gt;&lt;/div&gt;", {id: "foo", class: "a"}); 以保持与官方 API 文档的精神。

标签: javascript jquery html frameworks tags


【解决方案1】:

如果您只使用易于衡量的指标:第一个更好,因为它短 2 个字节。

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

那么,最后将前两个选项之一用于 div 是错误的吗?

不,该部分仅适用于“如果 HTML 比没有属性的单个标记更复杂”

【讨论】:

  • 好的,但是 xHtml 呢?
  • 您正在与一个设计为由 Web 开发人员调用的函数交谈,这些开发人员在让 Web 浏览器执行大量错误恢复方面有着悠久的历史,因此他们不需要学习 HTML确实有效。更重要的是,您提供的信息完全相同,只是使用了稍微不同的字符组合。
  • @Vixed 你没有意识到你传递给$('&lt;someElement&gt;') 的东西在后台被解析然后变成一个实际的dom元素,这就是它不需要结束标签的原因。看看 parseHtml() 如何在内部处理单个元素...它使用 document.createElement ... james.padolsey.com/jquery/#v=1.11.2&fn=jQuery.parseHTML
  • @Vixed — 里面多了两个字符的那个需要两个字节,所以加载它需要更长的时间。不,您不需要这两个字节。您不需要它们,因为正如反复说过的那样,它们将被忽略。
  • @Vixed 当你可以在性能测试中自己做这件事时,为什么要开始赏金呢?任何回答赏金的人都会猜测(可能会得到其中的一些)......或者为您提供您可以自己进行的性能测试
【解决方案2】:

查看 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,如果是,则查看它是否以&lt; 开头并以&gt; 结尾。

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

然后,记住正则表达式 rsingleTag 是:-

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

同时匹配"&lt;div&gt;""&lt;div /&gt;",返回div 作为group[1]

parseHTML 使用它返回 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)) {

forthis.attr(match, context[match]); 覆盖每个属性设置

因此,最后将前两个选项之一用于 div?

如上图,个人喜好。两者的工作方式相同。

【讨论】:

  • 所以这只是一个字节问题?
  • 是的。 2个额外,1个空格,1个/。这不会对性能产生任何真正的影响。
  • @Vixed — 正如我上周所说。
  • @Vixed — 不是真的。这只是显示了取消选择代码(我在评论中链接到)而不是总结它的工作。
  • @Quentin 我看到了,这就是为什么我会接受你的回答,但我不能将赏金分配给你。顺便说一句,我想把赏金分配给 BenG,但在这种气氛下,我会让投票决定。
【解决方案3】:

来自 jQuerys 网站:

它使 HTML 文档遍历和操作、事件处理、动画和 Ajax 等事情变得更加简单......

请注意,它没有提及 HTML 生成

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

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

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

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

请注意此benchmark 的性能显着提升。 (在 Chrome 中大约快 4 倍)。这个解决方案比上面描述的两个更快,本质上是Cross platform

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

【讨论】:

  • 我曾与一些强烈反对你在这里所做的事情的人合作过:div = $(div)。您最终会通过分配更改“div”的类型。也就是说我也不喜欢看到 $varName ...
【解决方案4】:

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

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

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

【讨论】:

    猜你喜欢
    • 2011-02-11
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多