乐趣区

重绘 、回流

重绘、回流
首先了解页面的呈现流程

浏览器把获取到的 HTML 代码解析成一个 DOM 树,HTML 中的每个 tag 都是 DOM 树的 1 个节点,根节点就是 document 对象(html tag)。用 firebug 或者 IE Develop Toolbar 等工具可看到 DOM 树,包括 display:none 隐藏,还有 js 动态添加的元素;
浏览器把所有样式(主要包括 css 和浏览器的样式设置)解析成样式结构体。在解析过程中会去掉浏览器不能识别的样式,比如 IE 会去掉 -moz 开头的样式,Firefox 会去掉_开头的样式;

DOM tree 和样式结构体结合后构建呈现树(render tree)。render tree 中每个 node 都有自己的 style,而 render tree 不包含隐藏的节点(比如 display:none 的节点,还有 head 节点),这些节点不会用于呈现,也不影响呈现,所以就不会包含在 render tree 中。(visibility:hidden 隐藏的元素还会包含在 render tree 中,因为会影响布局(layout),会占有空间。根据 CSS2 的标准,render tree 中的每个节点都称为 box(Box dimensions),box 的所有属性:width,height,margin,padding,left,top,border 等;

render tree 构建完毕后,浏览器根据 render tree 来绘制页面。

重绘与回流的特征

当 render tree 中的一些元素的外观、风格等不会影响布局的属性改变,比如 bachground-color,这就称为重绘。
当 render tree 中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就称为回流。每个页面在第一次加载的时候就回流了一次。

注:重绘不一定会引起回流,回流一定引起重绘。任何对 render tree 中元素的操作都会引起回流或重绘。
如何减少回流、重绘

当元素的几个样式同时改变时定义一个新的 className,不要一个一个改变元素的样式属性;
使用 documentfragment 或 div 等元素进行缓存操作;
先 display:none 隐藏元素,然后对元素进行所有操作,最后再显示该元素;
不要经常访问会引起浏览器 flush 队列的属性,如果想要访问先读取到变量中进行缓存;

会引起浏览器 flush 队列的属性:
offsetTop, offsetLeft, offsetWidth, offsetHeight scrollTop/Left/Width/Height clientTop/Left/Width/Height width,height 请求了 getComputedStyle(), 或者 ie 的 currentStyle
让元素脱离动画流,减少回流的 render tree 的规模;
$(“#block1”).animate({left:50});
$(“#block2”).animate({marginLeft:50});

尽可能在 DOM 树的最末端改变 class(可限制回流的范围);
避免设置多层内联样式(将样式合并在一个外部类,仅产生一次回流);
动画效果应用到 position 属性为 absolute 或 flex 的元素上;
避免使用 table 数据;
避免使用 CSS 的 JavaScript 表达式。

退出移动版