DOM的重排和重绘

1. 前言

废话不多说,探究一下Dom渲染的本质。其实也是《高性能的javaScript》写的。
浏览器中Dom的实现和javaScript是分开的,每次通过javaScript操作DOM都是需要付出十分昂贵的代价,所以我们只能想尽办法,减少操作DOM次数,尽量自己先在javaScript中实现

2. 由来

当你浏览器下载完所有的组成元素,HTML标记啊,js啊,图片啊等等,浏览器会解析文件种下两个树,DOM树和渲染树。顾名思义,DOM树,表示结构,里面带了各种节点;而渲染树,表示显示,里面带了各种需要被其他人看见的节点。
接下来,当两棵树创造完毕之后,浏览器就可以开始绘制页面上的元素了。

3. 两个动作

当DOM的改变影响到了元素的几何属性(宽或高),比如你加了文字或者改变了边框的高度,导致浏览器需要重新计算元素的几何属性,而且其他元素的几何属性和位置也会因此改变受到影响。
浏览器使渲染树上受到影响的部分失效,然后重新构建渲染树,这个过程叫重排
之后,浏览器会重新绘制页面上受影响的部分,这个过程叫重绘
当然,不是所有的DOM操作都会导致这重排,只要你不影响到页面布局,假如你只是修改了背景颜色,那只会触发重绘。

4. 什么时候会出发重排

  • 添加或者删除课件的DOM元素
  • 元素位置的改变
  • 元素尺寸的改变(边距、填充、边框宽度、自身宽度、自身高度等属性的改变)
  • 内容的改变,例如:文本的改变或者图片被其他不用尺寸的替换了
  • 最初页面的渲染
  • 浏览器窗口改变尺寸

注意:根据改变的性质,渲染树上或大或小的一部分需要重新计算。某些改变可导致重排版整个页面:例如,当一个滚动条出现时。

重排事件这么昂贵,大多数浏览器通过队列化修改和批量显示优化重排版过程。然而,你可
能(经常不由自主地)强迫队列刷新并要求所有计划改变的部分立刻应用。获取布局信息的操作将导致刷
新队列动作,这意味着使用了下面这些方法:

  • offsetTop, offsetLeft, offsetWidth, offsetHeight
  • scrollTop, scrollLeft, scrollWidth, scrollHeight
  • clientTop, clientLeft, clientWidth, clientHeight
  • getComputedStyle() (currentStyle in IE)(在 IE 中此函数称为 currentStyle)

布局信息由这些属性和方法返回最新的数据, 所以浏览器不得不运行渲染队列中待改变的项目并重新排
版以返回正确的值

说都这儿就让我想起来,当年第一次写动画的时候,啥也不懂,通过js来不断的获取target的offsetTop,来判断位置,导致在手机端特别卡顿,罪过。如今看到这本书,觉得我怎么就没早点看这本书呢?

5. 最小化重排和重绘

  • 合并DOM操作逻辑,争取最后一次成功
  • 批量修改DOM操作时,可以先把它脱离文档流(浮起来或者隐藏或者删除),再批量的逻辑修改,最后回归文档流
  • 当你查询布局信息如偏移量、滚动条位置,或风格属性时,浏览器会刷队列并执行所有修改操作,以返回最新的数值。最好是尽量减少对布局信息的查询次数,查询时将它赋给局部变量,并用局部变量参与计算
  • 将元素提出动画流,position:absolute,尽量避免影响到其他的元素
  • IE从7开始,支持在任何元素上:hover,但是大量使用,会降低反应速度,IE8尤其明显,很长的列表慎用
  • 采用托管技术,使其冒泡到父节点