“innerHTML += ...” vs “appendChild(txtNode)”

IT技术 javascript dom
2021-01-27 17:17:00

问题是,使用innerHTML 比较连接并将文本节点附加到现有节点。幕后发生了什么?

到目前为止,我对此的想法:

  • 我猜两者都导致了“回流”。
  • 据我所知,后者(附加一个文本节点)也会导致 DOM 的完全重建(正确吗?他们都这样做了吗?)。
  • 前者似乎有一些其他令人讨厌的副作用,例如导致以前保存的对子节点的引用指向我正在修改的 innerHTML 节点,不再指向“当前 DOM”/“子节点的正确版本”。相比之下,在附加子项时,引用似乎保持不变。为什么是这样?

希望大家帮我解答一下,谢谢!

2个回答

后者(appendChild)不使DOM的完整重建或甚至所有目标内的元件/节点。

前者(设置innerHTML)确实会导致目标元素内容的完全重建,如果您要附加,则不需要。

附加通过innerHTML += content使浏览器运行元素中的所有节点,构建一个 HTML 字符串以提供给 JavaScript 层。然后您的代码将文本附加到它并设置innerHTML,导致浏览器删除目标中的所有旧节点,重新解析所有这些 HTML,并构建新节点。所以从这个意义上说,它可能效率不高。(然而,解析 HTML 是浏览器所做的,而且它们真的非常非常快。)

SettinginnerHTML确实会使对您可能持有的目标元素中的元素的任何引用无效——因为这些元素不再存在,您删除了它们,然后在设置时放入新的(看起来非常相似)innerHTML

简而言之,如果您要附加,我会使用appendChild(或insertAdjacentHTML,见下文)。如果您要更换,在非常有效的情况下,使用innerHTML比通过 DOM API 自己创建树更好的选择(速度是其中的首要因素)。

最后,值得一提的是insertAdjacentHTML,这是一个函数,您可以使用它来使用 HTML 字符串将节点和元素插入到元素中或元素旁边。您可以使用它附加到一个元素:theElement.insertAdjacentHTML("beforeend", "the HTML goes here");第一个参数是放置 HTML 的位置;您的选择是"beforebegin"(在元素外,就在它的前面),"afterbegin"(在元素内,在开头),"beforeend"(在元素内,在结尾),和"afterend"(在元素外,就在它之后)。请注意,"afterbegin"and"beforeend"插入元素本身,而"beforebegin"and"afterend"插入元素的元素受所有主要桌面浏览器的支持,我不知道移动支持有多好(尽管我确定 iOS Safari 和 Android 2.x 及更高版本至少有它),但是垫片很小。

@skaffman:在这个时代,我希望这两者都可以在您使用的任何浏览器中使用。innerHTML是非标准的,但几乎得到普遍支持(给你一个想法,Prototype 和 jQuery 都依赖它)。appendChild是最老一代 DOM 级别的一部分,它将在那里。:-) 请注意,innerHTML. 例如,您无法通过innerHTML在某些浏览器上设置 TR 元素来替换表格行IE 会在您使用它时去除前导空白。表单元素可能是一个挑战。等等。
2021-03-11 17:17:00
@TK:浏览器支持怎么样?一种技术是否比另一种更可能适用于旧版和/或移动浏览器?
2021-03-13 17:17:00
来自我的 +1 :-) 我会说,如果您正在使用innerHTML,请不要在循环中使用它。这样做效率很低,因为您要多次启动解析器。我见过像for (var i=0; i < arr.length; i++) { node.innerHTML += arr[i]; }. 相反,应该使用变量并且innerHTML应该在循环之外设置。
2021-03-29 17:17:00
我上面的陈述已经过时了。innerHTML已标准化:dev.w3.org/html5/spec/embedded-content-0.html#dom-innerhtml
2021-03-29 17:17:00
@pyramation:设置innerHTML和阅读它之间存在很大差异正如我上面所说,当你阅读它时,浏览器必须遍历所有节点,构建它们的 HTML 表示。在页面上放置新内容时,几乎总是最好添加一个元素并设置它的innerHTML(因为浏览 HTML 字符串基本上是浏览器所做的)。但我永远不会推荐使用+=with innerHTML
2021-04-07 17:17:00

我创建了一个小要点,对innerHTML 和appendChild 之间的性能进行了比较。

最后一位以大比分获胜

https://gist.github.com/oliverfernandez/5619180

值得一提的是,这个要点代表了附加到现有 时的性能innerHTML,而不是替换整个节点的内容。
2021-03-17 17:17:00
请永远不要使用innerHTML!使用前请参阅已接受的答案。
2021-03-21 17:17:00