DOM操作的性能优化

我们都知道,DOM操作的效率是很低的,尤其是用JS操作DOM的时候,性能的优劣更是引发问题和争论的焦点。
这里我们先分析一个很简单的例子:

<ul>
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
...
</ul>

假设我们要对上面的1000个或者更多的 li 元素进行抽样显示(隐藏)的控制,照常理来讲,我们会习惯性地去遍历这些元素,加上相应class,或者直接写上内联样式。至少在我看来这是最简单最高效的操作。然而 试验 结果却出乎我的意料,IE和firefox的显示结果都出奇的慢,去网上找了答案:这其实和文档的回流(reflow)很有关系,Nicholas总结了引起reflow的一些因素,其结论就是:

  1. 当对DOM节点执行新增或者删除操作时。
  2. 动态设置一个样式时(比如element.style.width=”10px”)。
  3. 当获取一个必须经过计算的尺寸值时,比如访问offsetWidth、clientHeight或者其他需要经过计算的CSS值(在兼容DOM的浏览器中,可以通过getComputedStyle函数获取;在IE中,可以通过currentStyle属性获取)。

文章地址是:www.nczonline.net/blog/2009/02/03/speed-up-your-javascript-part-4/
怿飞师父在他的 blog 里也有提到更详细的因素,有兴趣的可以再去深入研究。
当然我写这篇文章的目的不是去翻译 Nicholas 的文章或是照搬他们的理论,而是想分享下我 测试 的心得:
测试地址(慎用,会卡哦~~~^_^):http://www.silentash.com/upload/domscript.html
     1. 现有主流浏览器对DOM的操作是各自为政的,IE&Chrome reflow过程很短或者说没有reflow,Firefox的reflow现象非常显著(脚本执行之后有很长时间去刷新DOM结构,而且是硬直时间),Opera次之。
     2. reflow过程中浏览器无法响应用户的操作。
     3. IE耗费的大部分时间是去获取DOM元素,比如在这个例子中我使用的是常规的getElementById方法,遍历获取元素的时候很耗费时间。而其他浏览器多半时间花在后续的DOM操作中。
     4. 只添加class不做样式处理不会触发reflow,只更改背景样式也不会触发reflow。
     5. Nicholas文中提到循环中的语句是会实时触发reflow的,但实际测试的结果是 reflow在执行环境结束之后才被触发, Dean Edwards 在其回复中也证实了这一点。
     6. 同数量的DOM操作,appendChild方法比更改样式的方法高效很多,也就是说display:none引起的reflow消耗比DOM节点的新增或删除要严重(firefox中尤其明显)
综上几点,再回顾刚才的例子,更高效的方法是用appendChild方法去增加需显示的DOM节点,于是便有了最后的 优化措施
     1. 预存储UL下的所有LI元素
     2. 获取需显示的LI列表
     3. 删除整个UL元素,这里用的是UL父元素.removeChild(UL),千万不要用innerHTML=”,火狐里会挂的很惨。
     4. 重建UL元素
     5. 逐个添加步骤2获得的LI元素到UL
     6. 添加UL到UL父元素。
这其中又有Fragment的问题,究竟什么时候该用Fragment?因为fragment仅仅是一个过渡容器,在本质上不能提升代码的效率。所以很简单,当你需要临时容器的时候就用fragment,当你不需要临时容器的时候就可以不用。上面的过程中UL的重建等于是一个fragment,直到所有的LI都添加进去,才append到文档中。上面的例子中,如果用ul.innerHTML = ”,则可以创建一个fragment作为替身……
另:例子 中用到的是原生的DOM操作方法,如果用集成库的话性能上还可再优化一些。

转载于:https://www.cnblogs.com/rongxh7/archive/2010/05/23/1742321.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值