接上浏览器渲染过程
经过对浏览器渲染过程的了解,最后两步就是渲染
,也就是在这个阶段出现了重排
与重绘
,也同时是最耗时的阶段。(意思就是说在第一次加载页面的时候,就会出现重排
与重绘
)。
重排(回流)
当DOM的变化影响到了元素的几何信息,浏览器需要重新计算元素的宽高信息和位置信息。这个过程叫重排。
触发的条件
1.添加或者删除可见的DOM元素;
2.元素尺寸改变——边距、填充、边框、宽度和高度
3.内容变化,比如用户在input框中输入文字
4.浏览器窗口尺寸改变——resize事件发生时
5.计算 offsetWidth 和 offsetHeight 属性
6.设置 style 属性的值
重绘
当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。
常见的引起重绘的属性:
浏览器的渲染队列
1 | div.style.left = '10px'; |
按照之上的来说,这段代码应该重排+重绘4次,但是浏览器的渲染队列会把所有会引起重排、重绘的操作放入渲染队列队列,直到达到一定数量,或者一定时间,才进行一次重排和重绘。让多次的重排和重绘合并为一次。
那么怎样会阻止多次的重排和重绘合并成一次呢?
1 | div.style.left = '10px'; |
这段代码会触发4次重排+重绘,因为为了获取精确的值,浏览器会立即重排+重绘,才能获取到。
强制刷新队列的style样式请求:
- offsetTop, offsetLeft, offsetWidth, offsetHeight
- scrollTop, scrollLeft, scrollWidth, scrollHeight
- clientTop, clientLeft, clientWidth, clientHeight
- getComputedStyle(), 或者 IE的 currentStyle
每一次的使用这些style的样式请求,要注意上下文,否则容易引起重排+重绘
优化
1.分离读写
1 | div.style.left = '10px'; |
这样的话只会引起一次重绘+重排
2.添加class或者id,或者一次性的改变样式
1 | el.className += " theclassname"; |
3.缓存布局信息
1 | // bad 强制刷新 触发两次重排 |
我对第一段的理解就是先读div.offsetLeft
的信息加1,赋值给div.style.left
,然后因为又取了div.offsetTop
导致要马上的重排+重绘,才可以获取到,然后加1,赋值给div.style.top
,之后又一次重排+重绘。
而第二段,先读两个属性信息,之后设置left和top,都进入渲染队列,没有读操作,所以只会重排+重绘一次。
4.使用position,设置属性为absolute或fixed
position属性为absolute或fixed的元素,重排开销比较小,不用考虑它对其他元素的影响。(我认为是因为absolute和fixed都会使元素彻底脱离文档流,所以才影响比较小)。
总结
重排必定重绘,而重绘不一定重排。
在写这个时候感觉有点直接抄别人的了,没怎么查资料哈哈哈哈哈。