浏览器的重绘与回流
2021-05-10 本文已影响0人
my木子
DOM操作为什么会影响性能
- 在浏览器中,DOM 的实现和 ECMAScript 的实现是分离的。比如 在 IE 中,ECMAScript 的实现在jscript.dll中,而 DOM 的实现在 mshtml.dll 中;在 Chrome 中使用 WebKit 中的 WebCore 处理 DOM 和渲染,但ECMAScript 是在 V8 引擎中实现的,其他浏览器的情况类似。所以通过 JavaScript 代码调用 DOM 接口,相当于两个独立模块的交互。相比较在同一模块中的调用,这种跨模块的调用其性能损耗是很高的。但 DOM 操作对性能影响最大其实还是因为它导致了浏览器 的重绘(repaint)和回流(reflow)
浏览器渲染流程
- 解析HTML,构建DOM树
- 解析CSS,生成CSS规则树
- 合并DOM树和CSS规则,生成渲染树
- 布局渲染树(Layout/reflow),负责各元素尺寸、位置的计算
- 绘制渲染树(paint),绘制页面像素信息
重绘和回流的定义
- 重绘(Repaint):改变元素外观属性,如:color,background-color 等。
- 回流(Reflow):当渲染树中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
- 回流必定会引发重绘,但重绘不一定会引发重绘
- 重绘回流的代价:耗时,导致浏览器卡慢
导致回流的因素
- 页面首次渲染(无法避免)
- 元素尺寸或位置发生改变
- 浏览器窗口大小发生改变(resize 事件发生时)
- 元素内容变化(文字数量或图片大小等等)
- 元素字体大小变化
- 添加或者删除可见的DOM元素
- 元素位置的改变,或者使用动画
- 激活CSS伪类(例如::hover)
- 查询某些属性或调用某些方法,
scrollTo()
、clientWidth
、offsetWidth
优化
CSS
- 避免使用
table
布局; - 将需要多次回流的元素脱离文档流( absolute 或 fixed );
- 避免使用CSS表达式(例如:calc())。
JS
- 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性;
- 先为元素设置display: none,操作结束后再把它显示出来;
- 如果需要创建多个 DOM 节点,可以使用 DocumentFragment 创建完后一次性的加入 document。
let ul = document.querySelector("ul");
let fragment = document.createDocumentFragment();
for (let i = 0; i < 5; i++) {
let li = document.createElement("li");
li.innerHTML = i;
fragment.appendChild(li);
}
ul.appendChild(fragment);