zoukankan      html  css  js  c++  java
  • 前端性能优化 —— reflow(回流/重排)和repaint(重绘)

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

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

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

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

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

    下面情况会导致reflow发生

    1:改变窗口大小

    2:改变文字大小

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

    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的操作.......

    }

     总结:大小不要改,操作要少(样式和增删dom),多用fixed和absolute,动画速度要平滑,减少dom层级,选用简单选择器(少用后代减少匹配),合并(offsetTop之类操作)

    参考链接:

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

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

  • 相关阅读:
    利用DTrace实时检测MySQl
    改进MySQL Order By Rand()的低效率
    RDS for MySQL查询缓存 (Query Cache) 的设置和使用
    RDS For MySQL 字符集相关说明
    RDS for MySQL 通过 mysqlbinlog 查看 binlog 乱码
    RDS for MySQL Mysqldump 常见问题和处理
    RDS for MySQL Online DDL 使用
    RDS MySQL 表上 Metadata lock 的产生和处理
    RDS for MySQL 如何使用 Percona Toolkit
    北京已成为投融资诈骗重灾区:存好骗子公司黑名单,谨防上当!
  • 原文地址:https://www.cnblogs.com/wangtong111/p/11385448.html
Copyright © 2011-2022 走看看