Reflow和Repaint简介

什么是回流(reflow)与重绘(repaint)?要回答这个问题,得先认识一下浏览器原理,最主要的是要了解浏览器如何渲染网页。

一、浏览器解析的大概工作流

当浏览器接收到 HTML 时,就会解析它,将其分解为浏览器所能理解的词汇,而这个词汇由于HTML5 DOM 规范定义,在所有浏览器中是保持一致的。然后浏览器通过一系列步骤来构造和渲染页面。如下概述:

  1. 使用HTML创建文档对象模型(DOM)。
  2. 使用CSS创建 CSS 对象模型(CSSOM)。
  3. 基于DOM和CSSOM 执行脚本(Script)。
  4. 合并DOM和CSSOM 形成渲染树(Render Tree)。
  5. 使用渲染树布局(Layout)所有元素的大小和位置。
  6. 绘制(Paint)所有元素。

如下图所示:

浏览器渲染网页

可以看到Reflow和Repain分别出现在了第五和第六步。因此我们给出下面的定义:

Reflow:对于每个DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式(浏览器的,开发人员定义的)来计算并根据计算结果将元素放到它出现的位置,这个过程称为Reflow。
Repaint:当各种盒子的位置、大小以及其他属性,例如颜色、字体大小都确定下来后,浏览器便把这些元素都按照各自的特性绘制了一遍,于是页面的内容出现了,这个过程称之为Repaint。

可见这两个过程都会影响性能的,因此我们需要了解一些常见的会引起repaint和reflow的一些操作,并且应该尽量减少以提高渲染速度。

二、引起Repain和Reflow的一些操作

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

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

注意:

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

三、如何优化?

Reflow是不可避免的,只能将Reflow对性能的影响减到最小。下面给出几条建议:

  • 避免逐项更改样式。最好一次性更改style属性,或者将样式列表定义为class并一次性更改class属性。
  • 把DOM离线后修改:
  • 1)使用documentFragment 对象在内存里操作 DOM。
    2)先把DOM给display:none (触发一次Repaint),然后你想怎么改就怎么改。比如修改100次,然后再把他显示出来。
    3)clone一个DOM节点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。

  • 不要把 DOM 节点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这个结点的属性。
  • 尽可能的修改层级比较低的 DOM节点。
  • 将复杂的元素绝对定位或固定定位,使它脱离文档流。
  • 尽量不要使用table布局。因为可能很小的一个小改动会造成整个table的重新布局。

认识了一些基本的浏览器的原理后,是不是更有信心了呢?有一天产品要你自定义一个滑条取代浏览器自带的滑条以获得一致外观。我们可以这样回答:自定义滑条会引起Reflow导致性能问题,即使IScoll这样成熟的方案也没解决这一问题,因为还是使用自带滑条为好。

发表评论

电子邮件地址不会被公开。 必填项已用*标注