乐趣区

DOM和CSS渲染过程摘抄021

DOM 和 CSS 渲染过程

DOM


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
</html>

一个简单的 html 页面如上所示。

DOM 有两个概念:

  • 解析
  • 渲染

DOM 解析

DOM 解析:就是把你所写的各种 html 标签,生成一个 DOM TREE,可以认为就是生成了一个最原始的页面,一点样式都没有,毫无 CSS 修饰。

DOM 渲染:浏览器会把本身默认的样式 + 用户自己写得样式整合到一起,形成一个 CSS TREE,而 DOM 渲染就是指 DOM TREE 和 CSS TREE 结合到一起,生成一个 Render TREE,呈现出一个带有样式的页面。

1)浏览器会解析三个东西:

一个是 HTML/SVG/XHTML,事实上,Webkit 有三个 C ++ 的类对应这三类文档。解析这三种文件会产生一个 DOM Tree。
CSS,解析 CSS 会产生 CSS 规则树。
Javascript,脚本,主要是通过 DOM API 和 CSSOM API 来操作 DOM Tree 和 CSS Rule Tree.
2)解析完成后,浏览器引擎会通过 DOM Tree 和 CSS Rule Tree 来构造 Rendering Tree。注意:

Rendering Tree 渲染树并不等同于 DOM 树,因为一些像 Header 或 display:none 的东西就没必要放在渲染树中了。
CSS 的 Rule Tree 主要是为了完成匹配并把 CSS Rule 附加上 Rendering Tree 上的每个 Element。也就是 DOM 结点。也就是所谓的 Frame。
然后,计算每个 Frame(也就是每个 Element)的位置,这又叫 layout 和 reflow 过程。
3)最后通过调用操作系统 Native GUI 的 API 绘制。

线程

js 是单线程,但是浏览器是多线程的。

浏览器会有不同的线程,比如说

  • GUI 渲染线程
  • JS 线程
  • 定时器触发线程 (setTimeout)
  • 浏览器事件线程 (onclick)
  • http 异步线程
  • …..

上面的几个线程,在同一个瞬间,只有一个线程起作用,也就是互斥的。比如说浏览器在执行 GUI 渲染线程呢,那么其他的 4 个进程,都处于挂起的状态,在队列里面呆着。
DOM 的渲染对应的就是 GUI 渲染进程;JS 的执行对应的就是 JS 线程;所以,DOM 的渲染与 JS 代码的运行,在同一瞬间只能有一个执行!

阻塞

阻塞 XXX 是指让 XXX 暂停了。比如 JS 的执行阻塞 DOM 解析,就是

DOM 解析 –> JS 执行 (此时 DOM 解析暂停) –> JS 执行完毕 –> DOM 继续解析

DOM 与 CSS

先看它俩之间的关系,也就是分析 CSS 的加载对 DOM 的解析和渲染的影响。
很明显,DOM 自己在那解析 DOM TREE 和 css 样式有啥关系啊,所以 css 不影响 DOM 解析。
也很明显,DOM 渲染就是要生成样式呢,肯定和 css 有关系啊,所以 css 影响 DOM 渲染。
结论:

  • css 的加载不会阻塞 DOM 的解析
  • css 的加载会阻塞 DOM 的渲染

DOM 与 JS

JS(加载和执行)都会阻塞 DOM 的解析,因为 JS 中可能会对 DOM 进行操作,可能改变 DOM 的结构,所以 JS 的加载和执行是会阻塞 DOM 解析的。
JS(加载和执行)都会阻塞 DOM 的渲染,同上面一样,因为 JS 中可能对样式进行操作。
注:html 中每遇到 < script > 标签,页面就会重新渲染一次,因为要保证标签中的 JS 代码拿到的都是最新的样式。
结论:

  • JS 的加载和执行会阻塞 DOM 的解析
  • JS 的加载和执行会阻塞 DOM 的渲染

CSS 与 JS

在线程那里说了,CSS 的加载会阻塞 JS 的执行,因为 CSS 的渲染 GUI 线程和 JS 运行线程互斥。
但是 CSS 不会阻塞 JS 的加载(浏览器可以预先扫描并下载)
注 1:

  • CSS、JS 之间的加载是否阻塞,这里不考虑,因为现代的浏览器都会预先偷看文档,并且下载。

注 2:

  • 这里的 JS 引入方式不包括 async 和 defer

结论:

  • CSS 的加载阻塞 JS 的运行,不阻塞 JS 的加载

Note: 简单提一句,请注意 visibility: hidden 与 display: none 是不一样的。前者隐藏元素,但元素仍占据着布局空间(即将其渲染成一个空框),而后者 (display: none) 将元素从渲染树中完全移除,元素既不可见,也不是布局的组成部分。

下面简要概述了浏览器完成的步骤:

  • 处理 HTML 标记并构建 DOM 树。
  • 处理 CSS 标记并构建 CSSOM 树。
  • 将 DOM 与 CSSOM 合并成一个渲染树。
  • 根据渲染树来布局,以计算每个节点的几何信息。
  • 将各个节点绘制到屏幕上。

优化关键渲染路径_就是指最大限度缩短执行上述第 1 步至第 5 步耗费的总时间

https://developers.google.com…

https://developers.google.com…

https://developers.google.com…

退出移动版