转 小辉_Ray DOM性能小记

 在使用DOM操作时,同样的效果用不同的方式来实现,性能方面也会有很大的差异。尤其在移动式设备上,资源本来就很有限,一旦DOM写不好的话操作就会非常卡顿。这个周末,就写个DOM性能小记吧。错漏之处,望多指教。

  1、浅说reflow

  首先讲讲最近我才了解到的一个比较深入且模糊的东西——reflow

  从字面上理解的话,reflow有回流、重排的意思。它是指在DOM内容更新或增删时发生的一个响应过程,可以理解为页面内容改变了,然后发生重新排版这样的一个行为。我们可以将执行DOM操作细分为以下三个过程:读取HTML内容——>页面reflow——>展示更新内容。

  由于reflow是一个重整布局和样式的过程,相当消耗性能。所以我们优化DOM性能实际上就是避免执行更多DOM操作,即减少reflow过程

  2、减少reflow常用方法

  【1】采用临时变量存储,一次性操作DOM

    以我笔记本为例,分别测试了以下两段代码:

 1 //代码1
 2 window.onload = function(){
 3     var oUl = document.getElementById(‘ul1‘);
 4     for (var i = 0; i < 10000; i++) {
 5         oUl.innerHTML +=i;
 6     }
 7 }
 8 //代码2
 9 window.onload = function(){
10     var oUl = document.getElementById(‘ul1‘);
11     var str = ‘‘;
12     for (var i = 0; i < 10000; i++) {
13         str +=i;
14     }
15     oUl.innerHTML = str;
16 }

  在chrome浏览器下用时取样如下,前五次为两段代码分别运行,后五次为放一起先后执行时间:

t/ms 1 2 3 4 5 6 7 8 9 10
代码1 9067.696 8900.826 9114.520 8987.592 9220.753 9344.496 8783.459 8797.731 9337.738 8835.503
代码2 4.100 1.883 2.177 2.262 2.416 5.464 2.053 1.891 2.053 1.975

                                                            

  从上面数据明显看得出,同样执行10000次拼接,代码二远快于代码一。

  不难得出结论:减少DOM访问,改用外部变量临时存储内容,最后再一步执行DOM操作的效率远高于分次执行DOM操作。

  代码二的速度约是代码一的4000倍,可粗略计算出,innerHTML每查找并赋值一次,用时就接近1ms。

 【2】采用class修改多个样式,一次性更改属性

    分别测试以下代码:

 1 //代码三
 2 window.onload = function(){
 3     var oUl = document.getElementById(‘ul1‘);
 4     for (var i = 0; i < 20000; i++) {
 5         if(i%2==0){
 6             oUl.style.fontSize = "18px";
 7             oUl.style.lineHeight = "30px";
 8             oUl.style.padding = "20px";
 9             oUl.style.width = "100px";
10             oUl.style.height = "100px";
11         }else{
12             oUl.style.fontSize = "16px";
13             oUl.style.lineHeight = "40px";
14             oUl.style.padding = "30px";
15             oUl.style.width = "200px";
16             oUl.style.height = "200px";
17         }
18     }
19 }
20
21 //代码四
22 window.onload = function(){
23     var oUl = document.getElementById(‘ul1‘);
24     for (var i = 0; i < 20000; i++) {
25         if(i%2==0){
26             oUl.className = "class1";
27         }else{
28             oUl.className = "class2";
29         }
30     }
31 }

  同样在chrome浏览器下测试执行用时如下,前五次为两段代码分开运行,后五次为两段代码放一起运行(排除电脑不同时间点运行的差异):

t/ms 1 2 3 4 5 6 7 8 9 10
代码3 346.540 471.160 322.437 327.363 335.818 283.553 346.819 318.261 313.144 333.789
代码4 38.666 20.042 19.550 26.465 27.294 38.429 33.793 37.031 34.928 36.221

                                        

  从上面的数据可以看出,通过设置class改变多个样式的方法比分次改变样式明显快得多。

  在不考虑js代码赋值运算增多带来了误差的情况下(实际上很小),代码4的方法平均耗时也比代码3的方法快10多倍。因为在代码3中,我每改变一个样式都会产生一次reflow,即reflow了5次。而在代码四中使用className却只reflow了一次,但一次reflow改变了多个样式

  这里需要注意的是,不是所有样式的改变都会产生reflow的。只有会影响布局的样式才会,例如width,height,display,line-height,margin,padding,font,background等等。诸如color,opacity,visibility等则不会,因为它们只会产生repaint。你可以想象得到,改变颜色、透明度等值对页面的结构是不会产生任何影响的。这里我就不展开讲了。

【3】采用变量存储节点属性值,减少获取次数

  测试代码:

 1 //代码5
 2 for (var i = 0; i < 10000; i++) {
 3         if(i%2==0){
 4             document.getElementById(‘ul1‘).style.left = document.getElementById(‘ul1‘).offsetHeight + 10 + "px";
 5         }else{
 6             document.getElementById(‘ul1‘).style.left = document.getElementById(‘ul1‘).offsetHeight - 10 + "px";
 7         }
 8     }
 9
10 //代码6
11 var u1 = document.getElementById(‘ul1‘);
12 var uW = u1.offsetHeight;
13     for (var i = 0; i < 10000; i++) {
14         if(i%2==0){
15             u1.style.left = uW + 10 + "px";
16         }else{
17             u1.style.left = uW - 10 + "px";
18         }
19 }

   分别执行以上代码10000次的10个时间样本对比:  

t/ms 1 2 3 4 5 6 7 8 9 10
代码5 1256.209 1175.189 1384.690 1241.207 1223.094 1371.524 1186.556 1176.889 1269.450 1215.922
代码6 20.633 14.353 17.901 19.665 31.405 20.503 24.451 18.909 23.883 14.472

  同样可以看出,代码6是明显比代码5运行速度快的。

  当我们知道某一个节点的某些属性值是确定时,这时候我们可以将这个值保存在变量中,而不需要每次重新获取。否则当运行次数达到一定量后,会严重影响程序执行的速度。因为当第一次使用变量获取某个节点的值时,页面就会只reflow一次,并把这个值保存在内存中。下次程序需要时从内存中取就可以了。而代码5中则每次都沿着document去读取这些值,这些值虽然没有改变,但这些值是浏览器需要计算才能获得的,所以每次都会reflow一次。

  会导致reflow的属性有offsetLeft/Top、offsetHeight/Width、scrollTop/Left/Width/Height、clientTop/Left/Width/Height等。

  养成使用这种方法的习惯,不但能提高程序性能,有时候还可以节省代码量,使程序更简洁。

时间: 2024-08-06 11:55:13

转 小辉_Ray DOM性能小记的相关文章

DOM性能小记

在使用DOM操作时,同样的效果用不同的方式来实现,性能方面也会有很大的差异.尤其在移动式设备上,资源本来就很有限,一旦DOM写不好的话操作就会非常卡顿.这个周末,就写个DOM性能小记吧.错漏之处,望多指教. 1.浅说reflow 首先讲讲最近我才了解到的一个比较深入且模糊的东西——reflow. 从字面上理解的话,reflow有回流.重排的意思.它是指在DOM内容更新或增删时发生的一个响应过程,可以理解为页面内容改变了,然后发生重新排版这样的一个行为.我们可以将执行DOM操作细分为以下三个过程:

DOM练习小记--简单的拼单词游戏

(资料源自<Head First Ajax>第七章) 书中另一个单页游戏案例,综合了DOM和事件处理,先总结一下页面布局和js编程的思路.涉及到服务端交互的暂时按下,毕竟还没有自己把服务端环境搭起来. 1) 内容简介 书中给的样本页面和样式是布置好的,初始静态页面如下: 4row*4col布局,每次初始化都会随机出现16个字母图片: 点击任意字母会把对应字母输入到旁边字母框中,每次提交前每个字母只能点击一次: 需要拼出一个合法的单词,OK后点击submit提交(Ajax): 如果合法则在分数框

web前端优化--DOM性能优化

1.DOM访问与修改的优化: DOM访问是有代价的,修改DOM则会引起DOM的重绘与重排,而这两种操作会消耗性能. (1)缓存DOM:将频繁访问的对象或属性使用变量缓存起来,每次访问的时候,直接使用变量,而不是再次去访问DOM. (2)减少重绘与重排: 批量修改:使用文档片段documentFragment.使用类名一次性修改多个样式.或者使用CSSText属性 如 ele.style.cssText = 'color:red;border:1px solid green'; 元素脱离文档流,再

SqlServer数据插入性能小记

对于SQL性能,已经很久没关注了.由于近期项目既没有几千万的海量数据也没有过多的性能要求,所以在性能上也就没下太多功夫.然而,前不久和朋友闲谈间话题一转就说到程序上了,他说他用Delphi做了个数据导入的功能,插入数据的时候感觉很慢.以个人对SQL的了解,就建议他使用批量插入的方式,并很认真的告诉他这样应该会快很多.而在实际工作中,类似批量导入数据的功能是非常常见的,也许一个不小心我们就搞挂了服务器.那就究竟要怎么做才能给服务器留条活路,让用户不用点完上传看部电影再看上传结果呢?为此做了个小实验

观看小辉老师mysql视频总结文档

第一章命令及解释 show databases; 查看数据库 create table t(id int,name varchar(20)); 创建表 desc t; 查看表结构 insert into t values(1,'bbk'); 插入表 select * from t; 查看表 delete from t; 删除表中内容,不会删除表本身 show tables; 查看表 select * from t; 查看表中内容 第二章版本相关知识 Mysql命名机制使用由3个数字和一个后缀组成

总结五个小技巧定位数据库性能问题

[e良师益友网]数据库的使用会随着业务的和数据的增长变得迟钝,当数据库性能变得越开越糟糕的时候,技术人员往往可以扭转局面,下面为你介绍几个技术人员使用常使用的判别数据库性能问题的方法 1.基础设施纵向升级.投入更多的计算资源是解决问题的通常办法,但这办法实际上并不一定会让性能获得提升.即使扩充了正确的资源池,能被有效利用 的资源数量仍然是有限的.对于承载于物理设备上的数据库而言,添加基础设施具有一定难度,而但虚拟或云托管的数据库则非常容易调配计算资源. 2.横向扩展.一些类似群集化MySQL的数

小程序操作DOM以及JS求取字符串算法(前端网备份)

//js获取字符串的字节长度 //这套算法一个汉字2字节,字母符号1字节,按一行40个字节算4行 getLength:function(val){ var str = new String(val); var bytesCount = 0; for (var i = 0, n = str.length; i < n; i++) { var c = str.charCodeAt(i); if ((c >= 0x0001 && c <= 0x007e) || (0xff60

关联查询一张小表。对性能有影响吗(mysql)

具体语句 SELECT dfm.id, dfm.member_code, dfm.member_name, dfm.recommend_code, dfm.member_rank, dfm.create_time, dfm.account, dfm.have_account, dfm.member_img, dfmr.rank_name, dfmr.grade_commission_ratio, dfm1.member_name AS recommendName FROM d_fx_member

CSS调试小技巧 —— 调试DOM元素hover,focus,actived的样式

最近学习html5和一些UI框架,接触css比较多,就来跟大家分享一下css中的一些调试技巧.之前做页面,css都是自己写的,所以要改哪里可以很快的找到,现在使用了UI框架,里面的样式是不可能读完的,所以就要通过调试来找到要修改的地方. 在调试CSS的时候,我们一般使用Chrome.Firefox.IE等浏览器自带的工具,快捷键都为F12.但是,我们要调试如hover的样式时,鼠标放上去才会显示,鼠标一走就看不到了,没办法看清楚css样式,还有就是浏览器自带的一些hover.foucs.acti