创建/附加节点与innerHTML

Posted

技术标签:

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

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

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

【问题讨论】:

【参考方案1】:

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

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

DOM DocumentFragments jQuery Performance Rules Improve your jQuery - 25 excellent tips Speed test: innerHTML versus DOM manipulation ... 一个真正测试速度的测试,对于任何想要在浏览器上收集一些当前数据的人来说都是值得的

【讨论】:

在 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 节点附加,除了由于其错误的正则表达式而导致额外的错误-基于标记的黑客攻击。

以上是关于创建/附加节点与innerHTML的主要内容,如果未能解决你的问题,请参考以下文章

使用循环创建新的div,在每个新div上附加子节点

将多个相似的 XML 节点附加到 XML 文档

将节点附加到 EMF 数据模型实例 XML

根据数据中的附加列更改 d3 Sankey 图中的节点颜色

var 不附加到全局

SASI 索引是节点级别还是集群级别?