• 关于Reflow和Repaint的更多细节

    Reflow是个很耗性能的过程
    服务器君一共花费 17.350 ms 进行了 3 次数据库查询,努力地为您提供了这个页面。
    广告很萌的

    Reflow 和 Repaint 这两个不是一回事。

    • Repaint:屏幕的一部分要重画,比如某个CSS的背景色变了。但是元素的几何尺寸没有变。
    • Reflow:意味着元件的几何尺寸变了,我们需要重新验证并计算Render Tree。是Render Tree的一部分或全部发生了变化。这就是Reflow,或是Layout。

    HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的几何尺寸发生了变化,需要重新布局,也就叫reflow。reflow 会从<html>这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置,在reflow过程中,可能会增加一些frame,比如一个文本字符串必需被包装起来。

    Reflow的成本比Repaint的成本高得多的多。DOM Tree里的每个结点都会有reflow方法,一个结点的reflow很有可能导致子结点,甚至父点以及同级结点的reflow。在一些高性能的电脑上也许还没什么,但是如果reflow发生在手机上,那么这个过程是非常痛苦和耗电的。

    所以,下面这些动作有很大可能会是成本比较高的。

    • 当你增加、删除、修改DOM结点时,会导致Reflow或Repaint
    • 当你移动DOM的位置,或是搞个动画的时候。
    • 当你修改CSS样式的时候。
    • 当你Resize窗口的时候(移动端没有这个问题),或是滚动的时候。
    • 当你修改网页的默认字体时。

    注:display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。

    多说两句关于滚屏的事,通常来说,如果在滚屏的时候,我们的页面上的所有的像素都会跟着滚动,那么性能上没什么问题,因为我们的显卡对于这种把全屏像素往上往下移的算法是很快。但是如果你有一个fixed的背景图,或是有些Element不跟着滚动,有些Elment是动画,那么这个滚动的动作对于浏览器来说会是相当相当痛苦的一个过程。你可以看到很多这样的网页在滚动的时候性能有多差。因为滚屏也有可能会造成reflow。

    基本上来说,reflow有如下的几个原因:

    • Initial。网页初始化的时候。
    • Incremental。一些Javascript在操作DOM Tree时。
    • Resize。其些元件的尺寸变了。
    • StyleChange。如果CSS的属性发生变化了。
    • Dirty。几个Incremental的reflow发生在同一个frame的子树上。

    我们来看一个示例:

    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!'));
    

    当然,我们的浏览器是聪明的,它不会像上面那样,你每改一次样式,它就reflow或repaint一次。一般来说,浏览器会把这样的操作积攒一批,然后做一次reflow,这又叫异步reflow或增量异步reflow。但是有些情况浏览器是不会这么做的,比如:resize窗口,改变了页面默认的字体,等。对于这些操作,浏览器会马上进行reflow。

    但是有些时候,我们的脚本会阻止浏览器这么干,比如:如果我们请求下面的一些DOM值:

    1. offsetTop, offsetLeft, offsetWidth, offsetHeight
    2. scrollTop/Left/Width/Height
    3. clientTop/Left/Width/Height
    4. IE中的 getComputedStyle(), 或 currentStyle

    因为,如果我们的程序需要这些值,那么浏览器需要返回最新的值,而这样一样会flush出去一些样式的改变,从而造成频繁的reflow/repaint。

更多 推荐条目

Welcome to NowaMagic Academy!

现代魔法 推荐于 2013-02-27 10:23   

本章最新发布
随机专题
  1. [PHP程序设计] 命令式编程范式 6 个条目
  2. [JavaScript程序设计] Web实时通信技术名词解析 5 个条目
  3. [移动开发] Android加载器Loaders 5 个条目
  4. [软件工程与项目管理] 开始了解Git 5 个条目
  5. [移动开发] Android抽屉导航NavigationDrawer 5 个条目
  6. [Python程序设计] Python数据类型 11 个条目
  7. [Python程序设计] Python HTTP服务器 7 个条目
  8. [移动开发] Layout_weight属性解析 5 个条目
  9. [运维管理] 路由器与交换机 4 个条目
  10. [C语言程序设计] 结构体基本知识 1 个条目
  11. [PHP程序设计] PHP数组的遍历 7 个条目
  12. [智力开发与知识管理] 信息的类型与结构 9 个条目
窗口 -- [博客]