1.什么是重排?
重排:若渲染树的一部分更新,且尺寸变化,就会发生重排。
(重绘:部分节点需要更新,但不改变其他集合形状。如改变某个元素的vidibility,outline,背景颜色等。且重绘不一定导致重排,但重排一定导致重绘。重排会产生比重绘更大的开销。)
2.重排和重绘何时会发生?
触发重排:
- 页面初始渲染,这是开销最大的一次重排;
- 添加/删除可见的DOM元素;
- 改变元素位置;
- 改变元素尺寸,比如边距、填充、边框、宽度和高度等;
- 改变元素内容,比如文字数量,图片大小等;
- 改变元素字体大小;
- 改变浏览器窗口尺寸,比如resize事件发生时;
- 激活CSS伪类(例如::hover);
- 设置 style 属性的值,因为通过设置style属性改变结点样式的话,每一次设置都会触发一次reflow;
- 查询某些属性或调用某些计算方法:offsetWidth、offsetHeight等;
触发重绘
- vidibility
- outline
- 背景颜色:color,background-color
- visibility:hidden(重排)
3.减少重排次数
1.避免逐项更改样式。最好一次性更改style属性,或者将样式列表定义为class并一次性更改class属性。
2.将DOM离线。(离线意味着不在当前的DOM树中做修改)
我们可以这样做:
- 使用display:none
- 通过documentFragment创建一个dom碎片,在它上面批量操作dom,操作完成之后,再添加到文档中,这样只会触发一次重排。
- 复制节点,在副本上工作,然后替换它!
3.将复杂的元素绝对定位或固定定位,使它脱离文档流。
4.不要使用table布局,可能很小的一个小改动会造成整个table的重新布局
5.避免多次读取offsetLeft等属性。
6.优化动画
7.使用visibility替换display:none,因为前者只会引起重绘,后者会引发回流(改变了布局)