Fork me on GitHub

回流和重绘

我们要明确页面在文档加载完成之后到完全显示中间的过程是

  1. 根据文档生成DOM树(包括display:none的节点)
  2. 在DOM树基础上根据节点的几何属性(margin/padding/width/height等)生成render树(不包括display:none、head节点但会包含visibility:hidden节点)
  3. 在render树基础上进行进一步渲染包括color,outline等样式

reflow:

当render树中的一部分或者全部因为大小边距等问题发生改变而需要重建的过程叫做回流

repaint:

当元素的一部分属性发生变化,如外观背景色不会引起布局变化而需要重新渲染的过程叫做重绘

回流一定会引发重绘 但是 重绘不一定引发回流

引发回流的情况 :

  1. 首当其冲自然是dom树结构变化,比如你删除或者添加某个node.
  2. 元素几何属性变化,包括margin,padding,height,width,border等
  3. 页面渲染初始化
  4. 获取某些属性。虽然浏览器引擎可能会针对重排做了优化,比如Opera,它会等到有足够 数量的变化发生,或者等到一定的时间,或者等一个线程结束,再一起处理,这样就只发生一次重排。但除了render树的直接变化,当获取一些属性时,浏览器为取得 正确的值也会触发回流。这样就使得浏览器的优化失效了。这些属性包括:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、 clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。所以,在多次使用这些值时应进行缓存。(这段我是直接引用的。。。)
  5. 浏览器窗口发生变化-resize事件发生时
1
2
3
4
5
6
7
8
var s = document.body.style;
s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 再一次 回流+重绘
s.color = "blue"; // 再一次重绘
s.backgroundColor = "#ccc"; // 再一次 重绘
s.fontSize = "14px"; // 再一次 回流+重绘
// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));

说到这里大家都知道回流比重绘的代价要更高,回流的花销跟render tree有多少节点需要重新构建有关系,假设你直接操作body,比如在body最前面插入1个元素,会导致整个render tree回流,这样代价当然会比较高,但如果是指body后面插入1个元素,则不会影响前面元素的回流。

-------------本文结束感谢您的阅读-------------