文章目录
- 什么是浏览器的渲染?
- 浏览器渲染过程
- 面试问点:
- 为什么操作DOM慢?
- 回流与重绘
- 那么,什么情况下会触发回流?
- 浏览器的优化
什么是浏览器的渲染?
简单的说就是浏览器将 HTML 代码解析出来,把解析出来后的结果画到页面上,相当于就是,告诉浏览器,第一个像素点上应该呈现什么颜色,依次类推,占满整个页面静态,为什么说是静态的呢,因为当用户发生交互,页面变化(滚动、刷新、跳转等),使页面改变后,浏览器得重新计算整个页面的像素,可想而知,是一个庞大的工作量。
浏览器渲染过程
浏览的渲染过程简单来说就是:解析、构建渲染树、布局、绘制、复合,的过程。
- 解析数据包得到HTML文件, CSS文件,构建DOM树: 字节数据 ==> 转换成字符串 ==> 得到(标记)Token ==> 转换成Node节点(通过对象描述代码) ==> 构建Dom树。
解析CSS: 将CSS文件转化为 CSSOM 树,描述页面中样式规则与它们是如何应用于各个元素。 - 构建渲染树:
DOM + CSSOM == render
树。(渲染树只会包含显示的节点) (例如 display:none 的不需要渲染) - 布局: 确定页面上每个元素位置和尺寸的过程,浏览器计算每个元素的位置,大小以及它的几何属性,修改页面样式可能触发重新布局(回流)。
- 绘制: GPU绘制,将渲染树中元素绘制到屏幕,每个元素被绘制到一个层中,组合在一起形成最终画面,当页面中元素样式的改变并不影响它在文档流中的位置时,浏览器会将新样式赋予给元素并重新绘制它。(重绘)。(以上五步为重点)
- 层叠与合成: 将不同图层组合在一起,形成最终可见的页面,图层是元素一部分或整个元素,取决于浏览器如何优化渲染过程。
- 交互: 用户与页面交互时(点击或滚动页面),浏览器需要重新执行一些步骤,例如重新布局和绘制。
面试问点:
为什么操作DOM慢?
在浏览器渲染过程中,DOM
操作是相对慢的,为什么?因为 js 引擎线程和渲染线程互斥,所以,当我们通过js
来操作DOM
的时候,就势必会涉及到两个线程的通信和切换,所以会带来性能上的损耗。
回流与重绘
浏览器的渲染过程中给出了这样两个概念:回流和重绘。回流:浏览器计算每个元素的位置,大小以及它的几何属性,修改页面样式可能触发重新布局。重绘:当页面中元素样式发生改变,且不影响它在文档流中的位置时,浏览器会将新样式赋予给元素并重新绘制它。
那么,什么情况下会触发回流?
- 页面初次渲染
- 增加、删除可见的
DOM
元素 - 改变元素的几何信息
- 窗口大小改变
而当非几何信息被修改时,会触发重绘。
并且回流必定触发重绘,重绘不一定回流。
浏览器的优化
浏览器会维护一个渲染队列,当改变元素的几何属性导致回流发生时,回流行为会被加入到渲染队列中,在达到阈值或者达到一定时间之后会一次性将渲染队列中所有的回流生效。
因此,有这样一段JS
代码:
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '10px';
div.style.height = '10px';
表面上看它们需要执行四次回流,但实际上只有一次。
但是如果在原来的基础上添加这些代码,回流又会重新变成4次,这又是为什么呢:
div.style.left = '10px';
console.log(div.offsetLeft)
div.style.top = '10px';
console.log(div.offsetTop)
div.style.width = '10px';
console.log(div.offsetWidth)
div.style.height = '10px';
console.log(div.offsetHeight)
这就不得不提到我们接下来要讲的,[offsetWidth]
属性会强制渲染队列刷新。
强制渲染队列刷新
这12个属性都会强制渲染队列刷新
offsetTop, offsetLeft,offsetWidth, offsetHeight,
clientTop, clientLeft, clientWidth, clientHeight,
socrollTop, scrollLeft,scrollWidth, scrollHeight