如何在考虑到最佳性能的情况下将包含许多节点的 HTML 字符串直接附加到现有 DOM 元素?
我的问题是,是否有人对如何将包含许多节点的 HTML 字符串直接附加到现有 DOM 元素并考虑到最佳性能有任何想法。
让我解释一下我在做什么。我正在创建一个 javascript 模板脚本。现在速度太快了。我能够在 3 秒多一点的时间内将 40,000 个多数组项从 JSON 作为 html 节点渲染到 DOM 中(Chrome 16 在 OSX macbook pro 上运行)。
解析字符串后,我通过 .innerHTML 将其插入到新创建的 span 标记中,然后将该 span 标记附加到 DOM。它非常快、高效而且圆滑,但是该死的,它就是行不通。为什么?因为它用无关的标签包装了节点,在某些情况下,这无疑会干扰 CSS,谁知道还有什么。因此,我需要能够将多个新创建的 DOM 节点直接附加到现有的 HTML 标签下。
因此,我从附加 span 标签(以及通过innerHTML 分配的所有 html)切换到循环该 span 的每个子节点并单独附加它们。但是,伙计,这速度慢得多吗?渲染 40,000 个条目需要近 20 秒,而不是 3 秒。
对于这个特定的项目,我将避开 jquery。而且,不,我从来没有预料到在现实情况下会有 40,000 个项目呈现到页面上。我这样做只是为了测试速度。我希望脚本尽可能快。
My question is if anybody has any ideas in how to append an HTML string containing many nodes directly to an existing DOM element with utmost performance in mind.
Let me explain what I am doing. I am creating a javascript templating script. Right now it is wicked fast. I'm able to render 40,000 multi-array items from JSON as html nodes into the DOM in just over 3 seconds (Chrome 16 running on OSX macbook pro).
After I have parsed the string I insert it into a newly created span tag via .innerHTML and then append that span tag to the DOM. Its bloody quick, efficient and slick, but damn, it just won't work. Why? Because it wraps the nodes with an extraneous tag and this will, undoubtedly in some cases, interfere with CSS and who knows what else. So, I need to be able to append multiple newly created DOM nodes directly under an existing HTML tag.
So I switched from appending the span tag (along with all of its html assigned via innerHTML) to looping through each child node of that span and appending them separate. But, man, is it much slower! It takes almost 20 seconds to render 40,000 entries as opposed to 3 seconds.
And I'm steering clear of jquery for this specific project. And, no, I'm never anticipating having 40,000 items rendered to a page in a real world situation. I'm just doing this to test the speed. I want the script to be absolutely as fast as possible.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用
document.createDocumentFragment()
。 (文档:msdn,
mdn)
阅读 John Resig(jQuery 和 Sizzle 的作者)的评论使用后的性能改进
document.createDocumentFragment()
。IE 支持
element.removeNode(false)
,它将从 DOM 中删除元素,将其子节点保留在 DOM 中。但这对其他浏览器没有多大帮助。Use
document.createDocumentFragment()
. (Docs:msdn,
mdn)
Read what John Resig (Author of jQuery and Sizzle) had to say about performance improvements from using
document.createDocumentFragment()
.IE supports
element.removeNode(false)
which will remove the element from the DOM, leaving its child nodes in the DOM. But that doesn't help you much with other browsers.要将包含许多节点的 HTML 字符串直接附加到现有元素,您可以使用:
插入AdjacentHTML(IE4、Ch1、FF8、Op7)。这是最好的选择,而且非常简单。
追加,前置,之后,之前,replaceWith(Ch54、FF49、Op39)。方便的 API,但仅适用于新浏览器。
带有 outerHTML 的临时节点(IE4、 Ch1、FF11、Op7)。在更改 outerHTML 之前,您应该将您的节点附加到另一个节点。
带有 innerHTML 的临时节点(所有浏览器)但您无法从 DOM 中删除此节点,因此这是最糟糕的选择。
使用innerHTML或其他东西解析HTML字符串,并将结果节点一一附加到所需元素(或使用下面的方法一次全部附加)。这可能仅适用于不支持 insertAdjacentHTML 的 FF7。但没有人使用这样的旧版本。
要一次附加多个节点(不是字符串),您可以使用:
追加,前置,之后 , 之前,replaceWith(Ch54、FF49、Op39)。
DocumentFragment(所有浏览器)。这是节点的临时容器。当您将容器附加到其他某个节点时,子节点将附加而不是容器。之后容器将包含 0 个子容器。看起来容器从 DOM 中消失了。
appendChild 或 insertBefore 多次(所有浏览器)。它的性能最差。
计算每个节点的outerHTML,串联结果到一个字符串并使用上述方法附加该字符串。性能未知,因此不推荐。
For append HTML string containing many nodes directly to an existing element you can use:
insertAdjacentHTML (IE4, Ch1, FF8, Op7). It is best option and very simple.
append, prepend, after, before, replaceWith (Ch54, FF49, Op39). Convenient API but works only in new browsers.
Temporary node with outerHTML (IE4, Ch1, FF11, Op7). Before changing outerHTML you should append your node to some another node.
Temporary node with innerHTML (all browsers) but you cannot delete this node from DOM so it is worst option.
Parse HTML string using innerHTML or something else and append resulting nodes one by one to needed element (or all at once using methods below). This may be needed only for FF7- that does not support insertAdjacentHTML. But no one use such an old version.
For append many nodes (not a string) at once you can use:
append, prepend, after, before, replaceWith (Ch54, FF49, Op39).
DocumentFragment (all browsers). This is temporary container for nodes. When you append the container to some other node there is child nodes are appending not the container. After that the container will contains 0 children. It looks like the container disappears from DOM.
appendChild or insertBefore many times (all browsers). It has worst performance.
Calculate outerHTML of each node, concatenate results to one string and append this string using methods above. Performance is unknown so not recommended.