浏览器渲染流程概述
大体来说,浏览器渲染过程为:
- 浏览器接收到一个html文档,渲染引擎会立即解析它,并将其html元素生成对应的DOM节点,组成一个”DOM树“。
- 浏览器解析来自CSS文件和html中内联的样式,然后根据这些样式信息生成css对象模型树(CSSOM tree),接着和上一步创建的DOM树合并为一个“渲染树“。
- 浏览器引擎根据渲染树计算出每个节点在其屏幕上应该出现的精确位置,并分配这组坐标,这样的过程称为“布局”,也称为“自动重排”。
- 浏览器遍历渲染树,调用每一个节点的paint方法来绘制这些渲染对象,通过绘制内容,最终在屏幕上展示内容。该过程称为”绘制“或者”栅格化“。
所谓的重排与重绘
而我们所说的重排(reflow),单指第3个步骤,重绘(repaint)则单指第4个步骤。
使用ChromeDevTools探索重绘与重排
实践是检验真理的唯一标准,接下来让我们用ChromeDevTools来探索一个简单的html在浏览器中初始化渲染以及后续更新的具体过程。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<style>
.left {
color: red;
width: 200px;
float: left;
}
.right {
float: right;
width: 200px;
border: 1px solid red;
}
</style>
<body>
<div class="container">
<div class="left" id="left">123</div>
<div class="right" id="right">1234</div>
<button id="changeColor">改变颜色</button>
<button id="changeHeight">改变高度</button>
</div>
<script>
document.getElementById("changeColor").addEventListener("click", () => {
// document.getElementById("left").style.color = "blue";
document.getElementById("left").innerHTML = '我变成了新值'
});
document.getElementById("changeHeight").addEventListener("click", () => {
document.getElementById("right").style.height = "100px";
});
</script>
</body>
</html>
如下图是使用Chrome DevTools获取的上述简单html文件初始化渲染的过程与时间:
上图中,蓝色部分Parse HTML就是创建dom树的过程。 紫色前半部分Recalculate style是创建cssom树的过程。 紫色后半部分Layout就是布局/重排的过程。 绿色部分Paint,渲染过程。
点击事件后只改变字体颜色:
可以看到,仅改变color属性,会执行上述2,4步骤,并没有执行Layout(重排)过程。
点击仅改变div高度:
仅改变高度,则会引起重排。
点击改变innerHTML:
而使用innerHTML改变dom内容,则会重新走一遍上述全部流程。
重排与重绘的引发条件
当我们改变dom的width,height这些可能会改变dom布局的style属性或者是改变浏览器宽高即触发onresize事件时,就会引起重排与重绘。
而当我们仅改变dom的color,background-color这些不会影响dom布局的style属性时,则不会触发重排仅会触发重绘。
不同浏览器对于相同style属性的重绘与重排规则也不尽相同, 想更细致的了解各个style属性是否触发重排与重绘,可以到cssTriggers深入了解。