昨天看了 lveyo老兄的"innerHTML的性能问题" 一文 http://lveyo.javaeye.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的实现方式
评论
iamjxc 2008-04-22
cloneNode 这种方法的问题是, 原来对象上的事件等会丢失
lveyo 2008-04-20
我也是用到的时候才发现老外的那篇文章的,也没想去研究为什么会有性能差异,还是你有钻研的精神,以后要多向你学习!
fins 2008-04-17
hax 哪里能下载到 gecko 的源代码啊 最好是最新的1.9 nightly的??
fins 2008-04-17
不知道为什么ie处理innerHTML时处理的那么好

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

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

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

FF超级慢

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

div1.onscroll= { div2.scrollLeft = div1.scrollLeft }
hax 2008-04-17
我看了一下gecko的实现。它是先取得一个range,然后range->deleteContents,然后range->createContextualFragment。

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

看来你是弄 android弄入魔了
差沙 2008-04-16
哦,确实有道理呀,看起来有点像是UI显示里面的双缓冲似的。
发表评论

您还没有登录,请登录后发表评论

fins
  • 浏览: 743365 次
  • 性别: Icon_minigender_1
  • 来自: 小胖儿的大城
  • 详细资料
搜索本博客
我的相册
89757367-bcf7-3449-ae1d-31a5a2021dd7-thumb
customHead
共 76 张
其他分类
存档
最新评论