问题是,使用innerHTML 比较连接并将文本节点附加到现有节点。幕后发生了什么?
到目前为止,我对此的想法:
- 我猜两者都导致了“回流”。
- 据我所知,后者(附加一个文本节点)也会导致 DOM 的完全重建(正确吗?他们都这样做了吗?)。
- 前者似乎有一些其他令人讨厌的副作用,例如导致以前保存的对子节点的引用指向我正在修改的 innerHTML 节点,不再指向“当前 DOM”/“子节点的正确版本”。相比之下,在附加子项时,引用似乎保持不变。为什么是这样?
希望大家帮我解答一下,谢谢!
问题是,使用innerHTML 比较连接并将文本节点附加到现有节点。幕后发生了什么?
到目前为止,我对此的想法:
希望大家帮我解答一下,谢谢!
后者(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 及更高版本至少有它),但是垫片很小。
我创建了一个小要点,对innerHTML 和appendChild 之间的性能进行了比较。
最后一位以大比分获胜