【每日面试题】重排和重绘有什么区别,什么会引发重排,什么会引发重绘

776 阅读3分钟

重排(回流)

当渲染树中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。每个页面至少需要一次的回流,也就是页面第一次加载的时候。

引发重排的原因

1. 页面首次渲染
2. 浏览器窗口大小发生改变
3. 元素尺寸或位置发生改变
4. 元素内容变化(文字数量或图片大小等)
5. 元素字体大小变化
6. 添加或者删除可见的 DOM 元素
7. 激活 CSS 伪类(:hover)
8. 设置 style 属性
9. 查询某些属性或调用某些方法
常见引起重排属性和方法
widthheightmarginpaddingdisplay
borderpositionoverflowclientWidthclientHeight
clientTopclientLeftoffsetWidthoffsetHeightoffsetTop
offsetLeftscrollWidthscrollHeightscrollTopscrollLeft
scrollIntoView()scrollTo()getComputedStyle()getBoundingClientRect()scrollIntoViewIfNeeded()

重绘

当页面元素样式的改变并不影响他在文档流中的位置时,这些属性只是影响元素的外观,风格,而不会影响布局的,浏览器会将新样式赋予给元素并重新绘制它,这个过程称之为重绘。

引发重排的原因

1. 字体颜色改变
2. 边框样式改变
3. 背景颜色、图片、定位、尺寸改变
4. 外边框颜色、样式
5. 外发光改变
常见引起重排属性和方法
colorborder-stylevisibilitybackgroundtext-decoration
background-imagebackground-repeatbackground-positionbackground-sizeoutline-color
outlineoutline-styleborder-radiusoutline-widthbox-shadow

回流必将引起重绘,而重绘不一定引起回流。

如果一个元素引发了回流,它就影响了父级以及兄弟节点的位置,他们都要重新渲染了,所以回流必定引发重绘。

优化

减少 DOM 操作

1. 最小化 DOM 访问次数,尽量混存访问 DOM 的样式信息,避免过度触发回流(重排)。
2. 如果在一个局部方法中需要多次访问同一个 DOM,则先暂存它的引用。

采用更优的 API 替代消费高的 API,转换优化消费高的集合

1. 用 querySelectAll() 替代 getElementByXX()
2. 开启动画的 GPU 加速,把渲染计算交给 GPU
3. 少用 HTML 集合(类数组)来遍历,因为集合遍历比真数组遍历耗费更高
4. 用事件委托来减少事件处理器的数量

减少重排

1. 避免设置大量的 style 属性,因为通过设置 style 属性改变节点样式的话,每一次设置都会触发一次 reflow (回流),所以最好是使用 class 属性
2. 实现元素的动画,它的 position 属性,最好是设为 absolute 和 fixed,这样不会影响其他元素的布局
3. 动画实现的速度的选择。比如实现一个动画,以 1 个像素为单位移动这样最平滑,但是 reflow 就会过于频繁,大量消耗 CPU 资源,如果以 3 个像素为单位就会好很多
4. 不要使用 table 布局,因为 table 中某个元素一旦触发了 reflow,那么整个 table 的元素都会触发 reflow。那么在不得已使用 table 的场合,可以设置 table-layout: auto; 或者是 table-layout: fixed; 这样可以让 table 一行一行的渲染,这种做法也是为了限制 reflow 的影响范围