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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2305654/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:42:45  来源:igfitidea点击:

"innerHTML += ..." vs "appendChild(txtNode)"

javascriptdom

提问by T.J. Crowder

The question is, comparing concatination using innerHTML and appending a text node to an existing node. What is happening behind the scene?

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

My thoughts around this so far:

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

  • I'm guessing both are causing a 'ReFlow'.
  • The latter (appending a text node), from what I know, also causes a complete rebuild of the DOM (correct? Are they both doing this?).
  • The former seems to have some other nasty side effects, like causing previously saved references to child nodes to the node I'm modifying innerHTML, to no longer point to 'the current DOM'/'correct version of the child node'. In contrast, when appending children, references seem to stay intact. Why is this?
  • 我猜两者都导致了“回流”。
  • 据我所知,后者(附加一个文本节点)也会导致 DOM 的完全重建(正确吗?他们都这样做吗?)。
  • 前者似乎还有一些其他令人讨厌的副作用,例如导致之前保存的对我正在修改 innerHTML 的节点的子节点的引用不再指向“当前 DOM”/“子节点的正确版本”。相比之下,在附加子项时,引用似乎保持不变。为什么是这样?

I'm hoping you people can clear this up for me, thanks!

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

回答by T.J. Crowder

The latter (appendChild) does notcause a complete rebuild of the DOM or even all of the elements/nodes within the target.

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

The former (setting innerHTML) does cause a complete rebuild of the content of the target element, which if you're appending is unnecessary.

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

Appending via innerHTML += contentmakes the browser run through all of the nodes in the element building an HTML string to give to the JavaScript layer. Your code then appends text to it and sets innerHTML, causing the browser to drop all of the old nodes in the target, re-parse all of that HTML, and build new nodes. So in that sense, it may not be efficient. (However, parsing HTML is what browsers doand they're really, really fast at it.)

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

Setting innerHTMLdoes indeed invalidate any references to elements within the target element you may be holding -- because those elements don't exist anymore, you removed them and then put in new ones (that look very similar) when you set innerHTML.

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

In short, if you're appending, I'd use appendChild(or insertAdjacentHTML, see below). If you're replacing, there are very valid situations where using innerHTMLis a better option than creating the tree yourself via the DOM API (speed being chief amongst them).

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

Finally, it's worth mentioning insertAdjacentHTML, which is a function that you can use to insert nodes and elements into or next to an element using an HTML string. You can append to an element with it: theElement.insertAdjacentHTML("beforeend", "the HTML goes here");The first argument is where to put the HTML; your choices are "beforebegin"(outside the element, just in front of it), "afterbegin"(inside the element, at the beginning), "beforeend"(inside the element, at the end), and "afterend"(outside the element, just in after it). Note that "afterbegin"and "beforeend"insert into the element itself, whereas "beforebegin"and "afterend"insert into the element's parent. Supported by all major desktop browsers, I have no idea how good mobile support is (although I'm sure iOS Safari and Android 2.x and up have it, at least), but the shimis tiny.

最后,值得一提的是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 及更高版本至少有它),但是垫片很小。

回答by oliferna

I've created a small gist with a performance comparison between innerHTML and appendChild.

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

The last one wins by a wide margin

最后一位以大比分获胜

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

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