浏览器是如何渲染页面的
当浏览器收到HTML文档后,会产生一个渲染任务,并将其传递给主线程的消息队列,在事件循环的调度下,主线程会从消息队列中取出渲染任务,并将其传递给渲染进程。
整个渲染进程分为多个阶段,分别是: HTML解析——》样式计算——》布局——》分层——》绘制
渲染的第一步是解析HTML文档。 解析过程中遇到link会去下载css文件,遇到script会停止解析HTML,转而等待全局代码解析执行完成后,才能继续解析HTML文档,因为JS代码的执行过程可能会修改DOM树。最终生成DOM树和CSSOM树。DOM树和CSSOM树合并后生成渲染树。渲染树的每个节点都是可以渲染的,包括文字、图片、视频、音频等。
样式计算 主线程会遍历DOM树,并根据每个DOM节点的CSS样式,生成每个DOM节点的样式。这一步完成之后,会得到一个包含所有DOM节点样式信息的样式树。
布局 布局会得到布局树,布局阶段会依次遍历DOM树的每一个节点,计算节点的几何信息,包括位置、大小等,最终生成布局树。 但是大部分时候布局树和DOM树不是一一对应的,比如display:none的元素,就不会出现在布局树中。
分层 主线程会根据一套复杂的策略对整个布局树进行分层。分层的好处是,可以方便地进行图层优化,比如将重叠的元素放在同一个图层,或者将需要动画的元素放在同一个图层。将来某一个图层需要重绘时,只需要重绘这个图层即可。 滚动条 对得上下文 transform 等样式会影响分层的结果
绘制 绘制阶段会遍历分层后的图层,并根据每个图层的样式,生成每个图层的绘制命令。绘制命令会包含每个图层的绘制位置、大小、颜色等。
分块 分块阶段会根据绘制命令,生成多个绘制块。绘制块是绘制命令的集合,每个绘制块可以独立绘制。
光栅化 光栅化阶段会根据绘制块,生成多个位图。位图是绘制块的集合,每个位图可以独立绘制。
合成 合成阶段会根据位图,生成最终的页面。
什么是reflow
reflow是浏览器的一种优化策略,当页面需要重新计算布局时,浏览器会重新计算布局,并生成新的布局树。为了避免连续修改导致布局树反复计算,浏览器会使用队列来存储修改,当队列中的修改达到一定数量时,浏览器会一次性计算布局,并生成新的布局树。所以reflow是异步的。所以当JS获取属性时,就可能无法获取到最新的属性。因此,JS获取布局属性时会立即执行reflow,并返回最新的属性。
什么是repaint
repaint是浏览器的一种优化策略,当页面需要重新绘制时,浏览器会重新绘制,并生成新的位图。
为什么transform效率高
因为transform既不会影响布局,也不会影响绘制,所以浏览器会使用合成策略,将transform的图层放在一个单独的图层中,将来某一个图层需要重绘时,只需要重绘这个图层即可。