浏览器必备知识—回流&重绘
“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第4篇文章,点击查看活动详情”
页面渲染
-
layout
阶段:这个阶段其实就是我们所说的回流reflow
,浏览器会根据渲染树生成对应的几何信息,比如DOM
元素相对于浏览器视口的坐标以及大小,最终生成布局树- 如果不是页面初始化阶段,回流会使渲染树中受到影响的部分失效,并重新构造渲染树失效的部分,然后再重新计算元素的位置和几何信息生成布局树
painting
阶段:这个阶段其实就是我们所说的重绘repaint
,浏览器会根据layout
阶段生成的布局树将DOM
元素的几何信息以及大小转换为屏幕中的实际像素
构建渲染树的过程
- 遍历
DOM
树的所有可见节点
- 对于每个可见的节点,找到
CSSOM
树种对应的样式规则
- 结合可见节点和他们对应的样式,合并成渲染树
上面所提到的可见节点是什么呢?真的就是页面中看不到的节点吗?
所谓可见节点就是一些不会渲染到页面中的节点,比如 script
、meta
、link
等,还有通过设置 display: none
这一个属性隐藏的节点,其它属性比如说 visibility
或 opacity
只能算是让元素不可见,但对应的节点依旧会出现在渲染树中
总结一下,渲染树中是不会出现样式设置了 display: none
的节点以及 script
、meta
等不会渲染到页面中的节点的,但是通过 visibility
或 opacity
进行隐藏的节点依然会出现在渲染树中
什么时候会回流?
上文中也说了,回流的目的就是根据渲染树得到对应 DOM
元素相对于视口的位置和几何信息,那么当这些信息发生改变的时候就会触发回流。简单来说,当元素的布局、大小、内容等发生变化的时候浏览器就需要通过回流重新计算对应 DOM
元素在视口中的几何信息,如下的操作会导致回流:
- 添加或删除可见的
DOM
元素
-
元素的位置发生变化
- 页面中出现滚动条的时候,所有元素的位置都会发生变化从而造成全部元素回流
- 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
- 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
- 页面一开始渲染的时候(这是必须的,因为
HTML
渲染一定会走layout
阶段)
- 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
注意:回流一定会触发重绘,但重绘不一定会回流
浏览器优化
由于回流是比较消耗性能的一个浏览器操作,因为其涉及到了 DOM
节点位置和几何信息的计算,并且回流还会触发浏览器的重绘,所以现代的很多浏览器都会对回流进行优化,比如通过维护一个需要回流的队列,当队列到了一定长度或者到达一定时间才会去清空队列进行回流,这样浏览器就将多次回流重绘转换成了一次回流重绘,大大提高了性能
但是当你获取布局信息的操作的时候,会强制队列刷新进行回流,因为浏览器要确保你获取到的是相关 DOM
元素的最新信息,具体有以下的属性和方法会清空队列,但如果队列为空,则不需要再进行回流重绘,因为在此之间并没有改变位置和几何信息的操作:
offsetTop
、offsetLeft
、offsetWidth
、offsetHeight
scrollTop
、scrollLeft
、scrollWidth
、scrollHeight
clientTop
、clientLeft
、clientWidth
、clientHeight
getComputedStyle
getBoundingClientRect
减少回流和重绘
- 使用
cssText
将多次样式更改合并成一次样式更改,或者直接更新css
类名class
- 使用脱离文档流 -> 进行复杂操作 -> 恢复文档流的方法减少回流和重绘的次数,比如可以先为元素设置
display: none
,操作结束后再把它显示出来,这样总共就只造成了两次回流重绘,原先中间需要回流的地方都省去了
- 也可以利用这个思想使用绝对定位、文档片段
createDocumentFragment
或克隆元素cloneNode
的方式实现回流重绘
- 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来
- 使用
css3
硬件加速,可以让transform
、opacity
、filters
、will-change
这些动画不会引起回流重绘 (但会提高内存占用)
- 避免频繁操作
DOM
,创建一个documentFragment
,在它上面应用所有DOM操作
,最后再把它添加到文档中
- 使用
visibility
替换display: none
,因为前者只会引起重绘,后者会引发回流(改变了布局)
- 不要使用
table
布局,可能很小的一个小改动会造成整个table
的重新布局,让回流的压力变大
转载自:https://juejin.cn/post/7145663575548231694