简单理解渲染引擎和事件循环机制
浏览器既是搬运工,也是翻译官。
- 将枯燥的网络资源(html css js)从服务器“搬”到本地
- 将资源“翻译”成五彩的页面
- 接受并反馈用户的交互
渲染引擎
翻译的工作,最主要是由,浏览器的渲染引擎
做的。
翻译的过程如下:
- 访问网址的时候,服务器一般会首先返回 html 文件
- 渲染引擎,开始解析
html
文件,生成DOM
树。在这过程中遇到其他资源(css img js),会发出新的请求 - 识别并加载所有的
CSS
样式信息,生成CSSOM
树,注意这里的样式会添加到DOM
树的各个节点 - 将
DOM
树和CSSOM
树合并,将不可见的元素剔除,生成render
树(:after :before 伪元素会在此时被构建到 DOM 树中) - 计算页面中所有元素的相对位置、大小等信息,就有了
盒模型
- 开始把每一个页面图层转换为像素,并对所有的媒体文件进行解码,然后五彩的页面就显示出来了
总结下:
DOM
树 =>CSSOM
树 =>render
树 => 布局 => 绘制
重绘、重排、图层
页面不会一成不变的,JS 可以随意操作 DOM,从而会让渲染引擎再次翻译。
不同的操作,翻译成本不同,主要分为两种操作:
- 重排(回流):操作引发了 DOM 几何尺寸的变化(修改元素的宽高或隐藏元素等)时,于是需要重新计算元素 的几何属性(其他元素的几何属性和位置也会因此受到影响),然后再绘制出来。 对应的流程:可能更新
DOM
树 => 更新CSSOM
树 => 更新render
树 => 重新布局 => 重新绘制 - 重绘:操作只修改了未影响元素几何属性的样式(比如修改了颜色或背景色)时,就会跳过计算、直接绘制。 对应的流程: 更新
CSSOM
树 => 更新render
树 => 重新绘制
引发重排的操作:
- 修改元素的几何属性
- 改变 DOM 的结构,增减、移动等
- 获取一些特定属性的值:offsetTop|Left|Width|Height、scrollTop|Left|Width|Height、 clientTop|Left|Width|Height,这些属性均通过即时计算得到,于是浏览器为了获取这些值,也会进行回流
重排的代价很昂贵,尽量减少重排的操作,频繁引发重排,会让页面卡顿滴~
事件循环机制 event-loop
以上还没提到 JS 文件的翻译,JS 是由 JS 引擎翻译的。
先提一些名词:
- 宏任务(macro-task)队列:script(整体代码)、setTimeout、setInterval 等
- 微任务(microtask) 队列:Promise 等
- 函数调用栈
JS 引擎从开始执行 Script 脚本的时候,这本身就是一个宏任务,然后创建全局上下文,进栈
- 如果遇到
Promise
的then
代码,不会直接执行,会在此宏任务的内部,开启一个微任务队列,这个then任务
就是排队的第一人 - 如果遇到
setTimeout/setInterval
,不会直接执行,会另外开启一个宏任务,排在当前宏任务的后面,如果这个setTimeout
里面再遇到then
,也会在它的内部开启一个微任务队列 - 如果当前的宏任务的同步代码执行完了,会依次执行当前宏任务内部的,微任务队列里的任务
- 如果当前的宏任务的同步代码执行完了,微任务队列里的任务也执行完了,就会执行下一个宏任务
- 函数调用栈,每次执行一个函数,就创建了函数上下文,进栈,执行完,出栈,没啥说的,之前说过了
function app() { // s-1 setTimeout(() => { console.log("1-1"); // p-1 Promise.resolve().then(() => { console.log("2-1"); }); }); console.log("1-2"); // p-2 Promise.resolve().then(() => { console.log("1-3"); // s-2 setTimeout(() => { console.log("3-1"); }); }); } app(); // 1-2 1-3 1-1 2-1 3-1
画了个图,希望能帮助读者理解:
网络异常,图片无法展示
|