浅谈浏览器渲染、回流和重绘

概要

  1. 浏览器渲染的本质;
  2. 介绍回流 reflow 和重绘 repaint
  3. 如何优化性能;

浏览器渲染

一个普通的网页,浏览器在渲染前须要先构建 DOM(document object model) 和 CSSOM (css object model) 树。css

DOM

DOM 树是怎么来的呢?咱们先假设有一个网页由一些文本,一幅图片组成:前端

浏览器会通过:浏览器

  • 转换:浏览器从磁盘或网络读取 HTML 的原始字节,并根据文件的指定编码将它们转换成各个字符。
  • 令牌化: 浏览器将字符串转换成 W3C 标准规定的各类令牌,例如,“”、“”,以及其余尖括号内的字符串。每一个令牌都具备特殊含义和一组规则。
  • 词法分析:令牌转换成定义其属性和规则的“对象”。
  • DOM 构建:因为 HTML 标记定义不一样标记之间的关系(一些标记包含在其余标记内),建立的对象连接在一个树数据结构内,此结构也会捕获标记中定义的父子关系:HTML 对象是 body 对象的父项,body 是 paragraph 对象的父项,依此类推。

整个过程的最终输出是咱们这个普通页面的文档对象模型 (DOM),浏览器对页面的后续处理都会用到它。缓存

浏览器每次处理 HTML 标签时,都须要花费时间来完成上面的每一个步骤,一个页面有大量 HTML 处理时须要花费更多时间。网络

CSSOM

与处理 HTML 时同样,浏览器引擎须要将收到的 CSS 规则转化成浏览器能理解和处理的东西。数据结构

CSS 字节转换成字符,接着转换成令牌和节点,最后连接到一个称为“CSS 对象模型”(CSSOM) 的树结构内。构建 CSSOM 树是一个十分消耗性能的过程。布局

最后 CSSOM 树和 DOM 树合并成渲染树,并用它计算每一个可见元素的布局,而后输出给绘制流程,最终将像素渲染到屏幕上。性能

回流 reflow 和重绘 repaint

reflow 有些地方译成重排。字体

字面意思上理解重绘:从新描绘某个区域。优化

理解回流要复杂一些,咱们增删 DOM 节点,修改一个元素尺寸,页面布局和 DOM 树结构发生变化,确定须要从新构建 DOM 树,而 DOM 树与渲染树是紧密相连的,DOM 树构建完,渲染树也会随之对页面进行再次渲染。

重绘:对 DOM 操做简单修改样式(好比修改元素的 visibilitycolorbackground-color 等)、却并未影响页面布局时,浏览器不需从新计算元素的位置尺寸等,直接为该元素绘制新的样式。这个过程叫作重绘。

回流:对 DOM 操做致使 DOM 尺寸等属性的变化(好比修改元素的 widthheighttop)时,浏览器须要从新计算元素的属性,而后再将计算的结果绘制出来,这个过程叫作回流。

常见的会致使回流的操做:

  • 页面首次加载
  • 浏览器窗口尺寸改变
  • 元素尺寸或位置改变
  • 元素内容变化
  • 元素字体大小变化
  • 增删 DOM 元素
  • 查询或调用某些特定属性方法

总结:

  1. 回流每每代价比重绘大;
  2. 回流必定重绘,重绘未必回流。

现代浏览器优化

由于频繁修改 DOMCSSOM 自己是件特别耗费性能的事情,现代浏览器大多对于都作了必定的优化。好比会把一系列的操做放进队列机制来批量更新布局,至少一个浏览器刷新帧 16ms(即大多数显示屏幕的刷新率为 60Hz,一个刷新间隔为 1000ms/60)才会清空队列(节流优化~)。

但在获取布局尺寸等信息的时候,为了保证数据的准确性,队列中不管有没有会影响这些属性或方法返回值的操做,浏览器也会强制清空队列,触发回流与重绘。( IE 不保证有这些优化)

  • offsetTopoffsetLeftoffsetWidthoffsetHeight
  • scrollTopscrollLeftscrollWidthscrollHeight
  • clientTopclientLeftclientWidthclientHeight
  • widthheight
  • getComputedStyle()
  • getBoundingClientRect()

优化回流和重绘

  • 避免使用 CSS 表达式;
  • 使用 transform 替代 top
  • CSS3 硬件加速(GPU 加速);
  • 离线操做 DOM:把元素脱离文档流,而后对元素进行修改,这样只会致使重绘,而不会形成回流。
    • display:none:临时把元素 脱离文档流,进行批量操做后再放回。这样只会有一次回流;
    • createDocumentFragment:建立文档片断,一次性把内容放进文档;
  • 尽量在 DOM 树的最末端改变 class:减少回流的范围;
  • 将动画效果应用到 position 属性为 absolutefixed 的元素上,避免影响其余元素的布局,这样只是一个重绘,而不是回流;
  • JS 避免频繁读取会引起回流/重绘的属性:若是须要频繁使用,能够用变量把它缓存下来。

关注咱们

公众号@前端论道
相关文章
相关标签/搜索