1. 概念
- 重排:节点信息计算,即根据渲染树计算每个节点的几何信息(大小及位置)
- 重绘:渲染绘制,即根据计算好的信息绘制整个页面,渲染出最终的页面
- 浏览器渲染页面默认采用的是流式布局模型(Flow Based Layout),这一点很重要。
2. 导致重排因素
- 页面首次渲染
- 浏览器窗口大小发生改变
resize
- 元素尺寸或位置发生改变
var box = document.querySelector('.box');
//下面每一次操作,在浏览器没有优化的情况下,都会进行一次重排
box.style.width = '100px';
box.style.height = '100px';
box.style.margin = 10px;
box.style.padding = "5px";
//不仅牵扯到位置,还牵扯到BFC,从而进一步影响重排
box.style.position = "absolute";
box.style.top = "100px";
box.style.left = "100px";
box.style.display = "flex";
box.style.overflow = "hidden";
- 元素内容变化(文字数量或图片大小等等)
- 元素字体大小变化
font-size
- 添加或者删除可见的DOM元素。
- 激活CSS伪类(例如:
:hover
) - 设置
style
属性 - 查询某些属性或调用某些方法
//以下属性没有被浏览器优化,减少获取次数
offsetXXX...
clientXXX...
scrollXXX...
//以下方法没有被浏览器优化,减少调用次数
scrollIntoView()
scrollIntoViewIfNeeded()
scrollTo()
getComputedStyle()
getBoundingClientRect()
3. 减少重排
//只进行一次重排
box.style.cssText = 'width: 100px; height: 100px; margin: 30px; padding: 20px; border: 10px solid red';
//或者直接修改class类名
.mybox {
width: 100px;
height: 100;
margin: 30px;
padding: 20px;
border: 10px solid red;
}
box.className = 'mybox '
借用其他大佬的总结:
- 避免设置大量的style属性,因为通过设置style属性改变结点样式的话,每一次设置都会触发一次reflow,所以最好是使用class属性
- 实现元素的动画,它的position属性,最好是设为absoulte或fixed,这样不会影响其他元素的布局
- 动画实现的速度的选择。比如实现一个动画,以1个像素为单位移动这样最平滑,但是reflow就会过于频繁,大量消耗CPU资源,如果以3个像素为单位移动则会好很多。
- 不要使用table布局,因为table中某个元素旦触发了reflow,那么整个table的元素都会触发reflow。那么在不得已使用table的场合,可以设置table-layout:auto;或者是table-layout:fixed这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围
参考文献:
https://blog.csdn.net/cc_together/article/details/105497631
https://zhuanlan.zhihu.com/p/40605154
https://www.cnblogs.com/soyxiaobi/p/9963019.html