前端性能优化 —— reflow(回流)和repaint(重绘)

简要:整个在浏览器的渲染过程当中(页面初始化,用户行为改变界面样式,动画改变界面样式等)reflow(回流)和repaint(重绘) 会大大影响web性能,尤为是手机页面。所以咱们在页面设计的时候要尽可能减小reflow和repaint。css

什么是reflow和repaint(原文连接:http://www.cnblogs.com/Peng2014/p/4687218.html)html

reflow:例如某个子元素样式发生改变,直接影响到了其父元素以及往上追溯不少祖先元素(包括兄弟元素),这个时候浏览器要从新去渲染这个子元素相关联的全部元素的过程称为回流。web

reflow:几乎是没法避免的。如今界面上流行的一些效果,好比树状目录的折叠、展开(实质上是元素的显 示与隐藏)等,都将引发浏览器的 reflow。鼠标滑过、点击……只要这些行为引发了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引发它内部、周围甚至整个页面的从新渲 染。一般咱们都没法预估浏览器到底会 reflow 哪一部分的代码,它们都彼此相互影响着。express

repaint:若是只是改变某个元素的背景色、文 字颜色、边框颜色等等不影响它周围或内部布局的属性,将只会引发浏览器 repaint(重绘)。repaint 的速度明显快于 reflow浏览器

下面状况会致使reflow发生缓存

1:改变窗口大小app

2:改变文字大小dom

3:内容的改变,如用户在输入框中敲字ide

4:激活伪类,如:hover布局

5:操做class属性

6:脚本操做DOM

7:计算offsetWidth和offsetHeight

8:设置style属性

 

那么为了减小回流要注意哪些方式呢?

1:不要经过父级来改变子元素样式,最好直接改变子元素样式,改变子元素样式尽量不要影响父元素和兄弟元素的大小和尺寸

2:尽可能经过class来设计元素样式,切忌用style

var bstyle = document.body.style; // cache
 
bstyle.padding = "20px" ; // reflow, repaint
bstyle.border = "10px solid red" ; //  再一次的 reflow 和 repaint
 
bstyle.color = "blue" ; // repaint
bstyle.backgroundColor = "#fad" ; // repaint
 
bstyle.fontSize = "2em" ; // reflow, repaint
 
// new DOM element - reflow, repaint
document.body.appendChild(document.createTextNode( 'dude!' ));
 
对上面代码优化:
.b-class{
  padding:20px;
  color:blue;
  border:10px solid red;
  background-color:#fad;
  font-size:2em;
}
$div.addClass("b-class");
 

3:实现元素的动画,对于常常要进行回流的组件,要抽离出来,它的position属性应当设为fixed或absolute

4:权衡速度的平滑。好比实现一个动画,以1个像素为单位移动这样最平滑,但reflow就会过于频繁,CPU很快就会被彻底占用。若是以3个像素为单位移动就会好不少。

5:不要用tables布局的另外一个缘由就是tables中某个元素一旦触发reflow就会致使table里全部的其它元素reflow。在适合用table的场合,能够设置table-layout为auto或fixed,

6:这样可让table一行一行的渲染,这种作法也是为了限制reflow的影响范围。

7:css里不要有表达式expression

8:减小没必要要的 DOM 层级(DOM depth)。改变 DOM 树中的一级会致使全部层级的改变,上至根部,下至被改变节点的子节点。这致使大量时间耗费在执行 reflow 上面。

9:避免没必要要的复杂的 CSS 选择器,尤为是后代选择器(descendant selectors),由于为了匹配选择器将耗费更多的 CPU。

10: 尽可能不要过多的频繁的去增长,修改,删除元素,由于这可能会频繁的致使页面reflow,能够先把该dom节点抽离到内存中进行复杂的操做而后再display到页面上。

在div.first里面加入div.second,在div.second里面加入div.third:

$divS = $("<div class='second'></div>");

$(div.first).append($divS));//reflow

$divT = $("<div class='third'></div>");

$divS.append($divT);//reflow

优化代码:

$divS = $("<div class='second'></div>");

$divT = $("<div class='third'></div>");

$divS.append($divT);

$(div.first).append($divS));//reflow

或者:

var $divF = $(div.first);

$divS = $("<div class='second'></div>");

$divS.hide();

$(div.first).append($divS));

$divT = $("<div class='third'></div>");

$divS.append($divT);

$divS.show();//reflow

 

 

11:请求以下值offsetTop, offsetLeft, offsetWidth, offsetHeight,scrollTop/Left/Width/Height,clientTop/Left/Width/Height,浏览器会发生reflow,建议将他们合并到一块儿操做,能够减小回流的次数。

若是咱们要常常去获取和操做这些值,则能够先将这些值缓存起来例如:

var windowHeight = window.innerHeight;//reflow

for(i=0;i<10;i++){

  $body.height(windowHeight++);

  一系列关于windowHeight的操做.......

}

 

参考连接:

http://ued.alimama.com/front-end/quick-tips-among-yahoo-n-rules/

http://www.cnblogs.com/Peng2014/p/4687218.html