`

浅析 innerHTML 性能优化的原理

阅读更多



昨天看了 lveyo老兄的"innerHTML的性能问题" 一文 http://lveyo.iteye.com/blog/182891

该文介绍了一篇老外的关于提高innerHTML性能的文章.

老外的方法非常的怪异且神奇.

很多朋友在惊叹之余 对于背后的原理非常感兴趣.
受hax的提醒, 我看了一下webkit的代码.在这里我将分析的结果分享出来

说的不一定对 还请大家多多拍砖.


浏览器在 el.innerHTML = newHTML 时所做的工作:

====================================
原始方法

1) 创建一个fragment(document碎片)
2) 将 newHTML 设置到 fragment 内部 (这里怎么设置的不必关心,反正不是用的innerHTML 呵呵)
3) 清除el下的所有子节点 ,  类似 el.removeChildren()
4) 将fragment加入到 el内, 类似 el.appendChild(fragment)


====================================
文章里的新方法

1)克隆el节点(不包含子节点),相当于
newEl=document.createElement(el.tagName);
然或将el的所有属性赋值给 newEl  (通过 el.getAttribute  newEl.setAttribute)

2) 创建一个fragment(document碎片)
3) 将 newHTML 设置到 fragment 内部 (这里怎么设置的不必关心,反正不是用的innerHTML 呵呵)
4) 清除 newEl 下的所有子节点 ,  类似 newEl.removeChildren()
5) 将 fragment 加入到 newEl 内, 类似 newEl.appendChild(fragment)
6) 用 fragment 替换 el. 相当于 el.parentNode.replaceChild(newEl, el);  

新方法看起来比原始方法更麻烦, 但是为什么速度会更快呢?

关键点就是在 新方法的步骤 4 5 6 .
首先看4:
newEl 是clone的el,但是没有子结点,所以removeChildren很快就返回.相当于没有执行.
而且就算newEL有子结点,由于newEl不是一个在dom树里的节点, 也省去了其中复杂的一步
        if (n->inDocument())  n->removedFromDocument();
	

而 el.removeChildren 这个操作 相比之下自然要耗时很多.原因有三:removeChild操作比较复杂;el有子节点;el和el的子结点都在dom树内.


再来看5
newEl 和 fragment 本身都是脱离dom树独立存在的,这个操作速度也要比el.appendChild(fragment)快.

再来看6. 
6的操作就是 在el.parentNode中移除el,然后再在原始位置加入newEl. 这个步骤并没有速度优势.
但是 4 5 6这3个操作加起来,当el和newHTML足够复杂时,还是要比原始方法的 3 4 步更快


以上就是我的分析 有不对的地方 欢迎大家抛砖.
同时欢迎大家来贴一下 IE 和 ff的实现方式
10
2
分享到:
评论
9 楼 mml_net 2011-11-20  
:)
8 楼 javasweet 2009-10-28  
这种做法是否会造成内存泄露?因为把递归remove child节点的操作留给js引擎来做了
7 楼 iamjxc 2008-04-22  
cloneNode 这种方法的问题是, 原来对象上的事件等会丢失
6 楼 lveyo 2008-04-20  
我也是用到的时候才发现老外的那篇文章的,也没想去研究为什么会有性能差异,还是你有钻研的精神,以后要多向你学习!
5 楼 fins 2008-04-17  
hax  哪里能下载到 gecko 的源代码啊 最好是最新的1.9 nightly的??

4 楼 fins 2008-04-17  
不知道为什么ie处理innerHTML时处理的那么好

还有一个奇怪的问题关于FF的 :

为什么FF在"同步滚动"时 比别的浏览器慢很多 FF2 FF3都是如此

同步滚动:
就是说 你滚动一个overflow:auto的div 时
在 onscroll事件里 同步滚动另一个div
具体效果 可以下载我的 GT-GRID看一下
标题和表头同步滚动效果

FF超级慢

其实没做什么特殊的处理,伪代码如下:

div1.onscroll= {  div2.scrollLeft = div1.scrollLeft  }


3 楼 hax 2008-04-17  
我看了一下gecko的实现。它是先取得一个range,然后range->deleteContents,然后range->createContextualFragment。

而克隆替换法(暂且叫这个名吧)中,估计不需要deleteContents,而且createFragment时没有ownerDocument貌似也会少许多步骤。
2 楼 fins 2008-04-16  
利用 不在dom树中的节点 来加速 确实和双缓冲比较像啊 哈哈

看来你是弄 android弄入魔了

1 楼 差沙 2008-04-16  
哦,确实有道理呀,看起来有点像是UI显示里面的双缓冲似的。

相关推荐

    Javascript 性能优化的一点技巧

    ### JavaScript性能优化技巧详解 #### 引言 随着Web应用的日益复杂,JavaScript作为前端开发的核心语言之一,其运行效率直接影响着用户体验与整体性能。因此,掌握一定的JavaScript性能优化技巧对于提升应用程序...

    让你页面速度飞起来 Web前端性能优化(视频教程+ppt)

    ### Web前端性能优化知识点 #### 一、构建优化 **1.1 文件压缩与合并** - **文件压缩**:利用工具如UglifyJS、Terser等对JavaScript、CSS等静态资源进行压缩,减少文件体积,从而加快加载速度。 - **文件合并**:...

    innerHtml(转)

    5. **DOM操作的最佳实践**:可能还会涉及如何结合其他DOM方法和事件处理程序,优化使用`innerHTML`的策略,以提高代码的可维护性和性能。 6. **工具支持**:标签中的"工具"可能指的是开发者工具,如Chrome DevTools...

    Java性能优化【技巧】集锦.pdf

    Java 性能优化技巧集锦 Java 性能优化是 Java 开发中非常重要的一个方面,好的性能优化可以提升应用程序的运行效率和用户体验。在这篇文章中,我们将总结一些 Java 性能优化的技巧,包括通用篇、J2EE 篇、GUI 篇和 ...

    JavaScript性能优化的小知识总结共23页.pdf

    JavaScript是Web开发中不可或缺的一部分,它的性能优化对于提高网页加载速度和用户体验至关重要。这份"JavaScript性能优化的小知识总结共23页.pdf"涵盖了多个关键领域,旨在帮助开发者深入理解如何提升JavaScript...

    优化innerHTML操作(提高代码执行效率)

    以下是对innerHTML操作进行优化的一些策略: 1. **避免频繁使用innerHTML的“+=”操作**: 当我们使用`innerHTML += html`的方式添加内容时,浏览器会先解析现有的innerHTML,然后丢弃所有子节点,再将新的HTML...

    JavaScript性能优化技巧分享共8页.pdf.zip

    然而,随着现代Web应用的复杂性不断提升,性能优化成为开发者必须面对的重要任务。本文将深入探讨JavaScript性能优化的若干关键技巧,帮助你提升应用的运行效率和用户体验。 1. **代码结构优化** - **减少DOM操作*...

    Web开发性能优化参考

    19. **页面优化**:遵循Yahoo的YSlow或Google的PageSpeed Insights等工具提供的最佳实践,优化页面加载性能。 以上是针对Web开发性能优化的一些关键点,实际应用中还需结合具体项目和用户需求进行调整。优化的目标...

    关于在innerHTML中JS不执行的问题

    首先,我们需要理解`innerHTML`的工作原理。当设置一个元素的`innerHTML`时,浏览器会做以下几件事: 1. 清空当前元素的所有子节点。 2. 解析新设置的HTML字符串,生成一个DOM树。 3. 将新的DOM树插入到原始元素的...

    JavaScript性能优化的小知识总结共23页.pdf.zip

    JavaScript性能优化是提升Web应用响应速度和用户体验的关键领域。这份名为"JavaScript性能优化的小知识总结共23页.pdf"的文档很可能包含了多个方面的重要信息,旨在帮助开发者掌握提高JavaScript代码效率的方法。...

    innerHTML的简单应用

    innerHTML的简单应用

    通过 Dom 方法提高 innerHTML 性能

    `replaceHtml()` 函数的主要目的是通过创建一个新的元素,将新内容设置为该元素的 `innerHTML`,然后用这个新元素替换原有的元素,来优化 `innerHTML` 的性能。这种方法在 Firefox 2.0.0.6 和 Safari 3.0.3 beta ...

    innerHTML的使用

    innerHTML的使用document.getElementById("id").innerHTML = "contenttext";

    通过改变innerHTML的内容,动态增加选择项

    首先,我们要理解`innerHTML`的工作原理。`innerHTML`可以获取或设置一个元素的所有HTML内容。当我们设置`innerHTML`时,浏览器会解析新的HTML字符串,替换掉原有内容,然后重新渲染元素。这为我们提供了一种灵活的...

    javascript appendChild,innerHTML,join性能比较代码

    而在追求性能优化时,数组`join()`结合`innerHTML`的方法可以作为一个折衷方案。记得在进行性能优化时,应先确保代码的可读性和可维护性,再考虑性能优化,因为性能问题通常只在处理大量数据或者高频率操作时才变得...

    Javascript createElement和innerHTML增加页面元素的性能对比

    此外,现代浏览器优化了`innerHTML`的性能,使得它在处理大量元素时仍然具有竞争力。 总结来说,选择`createElement`还是`innerHTML`应根据具体场景来决定。如果关注性能,需要考虑元素的数量、是否涉及复杂的字符...

    JS提高优化性能完全秘籍.pdf

    ### JS提高优化性能完全秘籍 #### 执行效率优化技巧详解 **1. DOM操作优化** **1.1 使用DocumentFragment优化多次append** 在进行DOM元素频繁操作时,特别是需要频繁地向DOM树中添加元素时,直接使用`...

    利用innerHTML实现隐显效果-两种实现方法

    首先,我们需要理解innerHTML的工作原理。innerHTML允许我们获取或设置一个元素的所有子节点,包括文本、HTML标签等。当我们修改一个元素的innerHTML时,浏览器会重新解析该元素的内容,生成新的DOM子树,从而实现了...

Global site tag (gtag.js) - Google Analytics