【问题标题】:create/append node vs innerHTML创建/附加节点与innerHTML
【发布时间】:2010-12-14 05:36:36
【问题描述】:

有人有充分的理由使用其中一种吗?据我所知,create/append node 只是防止您创建无效代码,而 innerHTML 允许您一次注入多个节点。

鉴于我需要插入几个标签,使用 innerHTML 似乎很有意义。有没有人有不同的看法?

【问题讨论】:

    标签: javascript insert append innerhtml


    【解决方案1】:

    这始终是一个有争议的论点,部分原因是从标准的角度来看,innerHTML 的起源有些可疑。我认为 QuirksMode 文章仍然相关,但我很想看到它更新。也许contactppk 会更新它们,尽管我确信他很忙。我们都可以从我们在 Web 开发中所做的假设的性能测试中受益。到底索赔需要硬数据来证明,否则真的只是说说而已。

    无论如何,我进行了一些搜索,发现了一些与此讨论相关的有趣文章。我不记得以前听说过 DocumentFragments,它们真的很有趣。

    【讨论】:

    • 在 Win7 上使用速度测试链接 innerHTML 与片段: - Firefox 10.0.2 两种方法的执行情况大致相同(每次不同的方法稍快!) - Chrome (16.0.912.75 m) innerHtml始终快 50%。
    【解决方案2】:

    鉴于我需要插入几个标签,使用 innerHTML 似乎是有意义的。

    只有“几个”?那么速度不是问题。当您创建一百个时,您必须考虑自己在做什么。真正的问题不是创建问题,而是随着您添加每个额外元素,子节点列表操作变得越来越慢。

    至于追加,你真的别无选择。你不能在不丢失现有内容的情况下设置 innerHTML,所以除非你对序列化和重新解析它感到满意(这会消除任何不可序列化的数据,如表单内容、JavaScript 属性/引用和事件处理程序),否则你最终会设置另一个元素的 innerHTML 并一个一个地移动每个子元素。这就是许多框架所做的事情,它通常比手动 create-and-appendChild 还要慢。

    根据您的情况(特别是:目标元素中已经有多少子节点,以及您要添加多少?)将操作分解为 DocumentFragment 上的较小操作会更快,其子节点可以一次性而不是一个接一个地附加到一个元素的子元素。这要快得多。不幸的是,不能在 DocumentFragment 上设置 innerHTML

    使用 Range 对象一次移动大量 HTML 可能还有更快的 hack,但不幸的是,Range 是高度跨浏览器的变量。不过,在我看来,有人应该能够从 IE 的 range.pasteHTML 和 W3 的 range.extractContents 构建一个快速的 append-html。有人愿意吗?

    据我所知,创建/附加节点只是防止您创建无效代码

    潜在的无效标记不仅仅意味着您的应用程序在某些浏览器中中断。当你盲目地将 HTML 拼接在一起而不像白痴一样转义时:

    element.innerHTML= '<a href="'+url+'">'+title+'</a>';
    

    那么你有一个客户端跨站点脚本安全漏洞,它和服务器端漏洞一样糟糕。

    当然,您可以通过在单独的步骤中创建元素并设置其内容来妥协。例如:

    element.innerHTML= '<table>'+'<tr><td>X</td><td><a href="#">go</a></td></tr>'.repeated(urls.length)+'</table>';
    for (var i= 0; i<urls.length; i++) {
        var row= element.firstChild.rows[i];
        row.cells[0].firstChild.data= urls[i];
        row.cells[1].firstChild.href= urls[i];
    }
    

    (string.repeated 不是标准的 JavaScript,但它在这里的使用是显而易见的。)

    【讨论】:

      【解决方案3】:

      如果你使用这个技巧,DOM 操作会更快!

      这很慢:

      var target = document.getElementById('whatever');
      for (a = 0; a<10000; a++) { 
      var newnode = document.createElement('div'); 
      newnode.textContent = a;
      target.appendChild(newnode) }
      

      这很快:

      var target = document.createElement('span')
      for (a = 0; a<10000; a++) { 
      var newnode = document.createElement('div'); 
      newnode.textContent = a;
      target.appendChild(newnode) }
      document.getElementById('whatever').appendChild(target);
      

      第一个示例将新创建的节点附加到已包含在主体内的节点上,因此每次都会进行刷新。

      第二个示例将新创建的节点附加到不在正文范围内的“缓冲区”节点,因此在将缓冲区节点放置在正文范围内之前不会进行刷新。自己试试吧!

      【讨论】:

        【解决方案4】:

        如果性能很重要,很高兴知道innerHTML 相对较快,尤其是在 MSIE 中:http://www.quirksmode.org/dom/innerhtml.html

        然而,它最初是“Microsoft 专有”属性和/或不是真正的“OO”的不良形象。

        【讨论】:

        • innerHTML 在任何情况下都不是最快的。在 Safari 中,DOM 操作平均为 8 毫秒,而 innerHTML 平均为 32 毫秒。
        • 链接的文章有点旧了,Safari 现在已经是 4 岁了。这可能会有所不同。顺便说一句,我很好奇 Chrome 将如何适应结果。众所周知,它在 JS/DOM 中非常快。
        【解决方案5】:

        我相信在某些平台上,使用 DOM 函数而不是 innerHTML 会提高性能,因为不需要进行昂贵的 HTML 解析。

        【讨论】:

        • 根据这个页面,innerHTML 更快。 quirksmode.org/dom/innerhtml.html
        • @Tmdean:20 个月很长。
        • 一些操作使用 DOM 节点操作更快,一些操作使用 HTML 字符串解析更快。您无法说一种方法天生就比另一种更快。
        • 解析 HTML 成本高是“常识”。但事实上,解析 HTML 在浏览器中是高度优化的,而且速度非常快。事实上,速度如此之快,以至于在许多情况下,分配给 .innerHTML 的效果最好。
        【解决方案6】:

        这取决于你的目标是什么。

        使用 DOM 方法将 html 插入文档将允许您在插入之前/之后进一步操作这些元素。

        【讨论】:

          【解决方案7】:

          不同之处在于通过 DOM 创建节点是标准化的,而 innerHTML 只是一个事实上的标准。我读过 innerHTML 可以更快。

          更好的选择是使用像 jQuery 这样的库来进行 DOM 操作。它将处理大多数跨浏览器的不兼容问题,并且比使用 DOM 方法更具可读性。

          【讨论】:

          • 你认为 jQuery 是如何附加内容的?显然,您相信无论采用哪种方式都是最好的,但是查看代码后,我可以告诉您,它只是在执行与其他所有人相同的 innerHTML 解析和 DOM 节点附加,除了由于其错误的正则表达式而导致额外的错误-基于标记的黑客攻击。
          猜你喜欢
          • 2011-04-07
          • 1970-01-01
          • 2020-03-17
          • 2011-07-10
          • 2020-03-19
          • 1970-01-01
          • 2016-11-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多