-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
简述回流和重绘之前,先来说一下浏览器的渲染过程:
- 解析HTML结构,生成DOM树,解析CSS,生成CSSOM树
- DOM树和CSSOM树合并后生成渲染树
- 渲染树只包含渲染网页所需的节点
- 根据视口大小,布局计算每个对象的精确位置和大小
- 最后一步是绘制,使用最终渲染树将像素渲染到屏幕上
参考web
看到第三步,只包含渲染网页所需的节点,如script、link等是不包括的,还有通过CSS隐藏的节点,如display:none。但是opacitye和visibility隐藏的节点,是会在渲染树上的,因为它们虽不可见,但是却占据物理空间。
回流
第四步中,计算每个对象的精确位置和大小,这个计算的阶段就是回流。即页面因为布局、元素大小位置等改变需要重新构建,就是回流。
每个页面至少经过一次回流,即初始化页面时候的第一次加载。
何时发生回流
- 添加或删除可见的DOM元素
- 元素的位置变化,如发生位移等
- 元素的尺寸变化,如大小、内外间距、边框等
- 内容变化较大,如文字变为图片等
- 初始化页面的第一次渲染
- 浏览器的窗口尺寸变化
现代的浏览器都是聪明的,自己有一些优化。每次修改时,不是立即操作,而是缓存在队列中,按照一定的时间顺序去执行。但是当获取offsetTop等位置大小信息时,会实时获取最新值。
重绘(重排)
有些元素需要更新属性,如背景色等,只影响元素外观,不影响大小和位置,即页面布局的,称为重绘。
由上面可知,回流必定引起重绘,但重绘不一定引起回流。
如何减少回流重绘
- 利用class名替换行内样式的依次赋值,或者使用cssText
// bad
el.style.padding = '10px';
el.style.margin = '10px';
// good
el.addClass('box');
el.style.cssText += 'padding: 10px; margin: 10px;';- 批量修改DOM
(1) 使元素脱离文档流
(2)对其进行修改
(3)将元素带回文档中
如何让DOM脱离文档流:
a. 先将元素隐藏,修改后再重新显示
b. 利用代码片段(document.createDocumentFragment)在当前DOM之外构建一个子树,操作后再拷贝回文档
c. 将原始元素拷贝到一个脱离文档的节点中,修改后再替换原来元素
- 避免多次读取offsetTop等属性,即那些需要立即操作DOM的数据,无法避免时进行缓存。
- CSS硬件加速,使用transform、opacity、filters动画时不会引起回流重绘。但是对background-color还是会引起。
- 比较复杂的动画效果,让其脱离文档流
想详细了解css硬件加速,可移步这里
参考你真的了解回流和重绘吗
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels