首先
我们都知道在修改dom节点的尺寸、显隐等影响浏览器布局从而重新构建Render Tree的过程就是回流,而只改变Render Tree中一些元素的外观风格不影响布局,会引起浏览器的重绘。 先看一段代码:
let container = document.getElementById('container')
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'
分析上面代码,可能会得到结果进行了3次回流,4次重绘,但是结果却是1次回流,1次重绘。这是为什么呢?
浏览器的回流重绘
现代浏览器大多是通过队列机制来批量更新布局,浏览器会将触发回流重绘的操作放在一个队列中,等队列中任务到达一定数量或时间间隔到达一个阈值时清空队列。如果是60HZ刷新率的话,至少要16.6ms为一个阈值。但是当你获取布局信息时,浏览器为了返回准确的测量值,会强制清空队列触发回流重绘,主要包括以下属性和方法:
- offsetTop、offsetLeft、offsetWidth、offsetHeight
- scrollTop、scrollLeft、scrollWidth、scrollHeight
- clientTop、clientLeft、clientWidth、clientHeight
- width height
- getComputedStyle()
- getBoundingClientRect()
- ...
应用
有如下的代码:
elementA.className = "a-style";
var heightA = elementA.offsetHeight; // layout is needed
elementB.className = "b-style"; // invalidates the layout
var heightB = elementB.offsetHeight; // layout is needed again
给元素elementA赋值某个类让其布局发生改变,这意味着浏览器必须回流。但浏览器并不会立即进行回流,它会延迟到下次回流时进行批量处理。但这段javaScript代码会在下次回流之前执行完成,因此在执行到读取offsetHeight时,浏览器必须暂停javaScript代码并重新绘制页面,以便获取准确的数值,所以更好的代码应该是这样的:
elementA.className = "a-style";
elementB.className = "b-style"; // invalidates the layout
var heightA = elementA.offsetHeight; // layout is needed
var heightB = elementB.offsetHeight; // layout is needed again
这篇文章就分享到这里了希望对大家有所帮助!