前端学习笔记之 浏览器如何渲染页面?

从 HTML 到 DOM

1. 字节流解码

把字节数据解码成字符数据的过程。

2. 输入流预处理

把字符数据进行统一格式化的过程。

3. 令牌化

令牌化包含两步:第一步是将字符数据转化成令牌(Token),第二步是解析 HTML 生成 DOM 树。

html 代码的标记过程:

  1. 初始化为“数据状态”(Data State);
  2. 匹配到字符 <,状态切换到 “标签打开状态”(Tag Open State);
  3. 匹配到字符 !,状态切换至 “标签声明打开状态”(Markup Declaration Open State),后续 7个字符可以组成字符串 DOCTYPE,跳转到 “DOCTYPE 状态”(DOCTYPE State);
  4. 匹配到字符为空格,当前状态切换至“DOCTYPE 名称之前状态”(Before DOCTYPE Name State);
  5. 匹配到字符串 html,创建一个新的 DOCTYPE 标记,标记的名字为 “html” ,然后当前状态切换至 “DOCTYPE 名字状态”(DOCTYPE Name 之State);
  6. 匹配到字符 >,跳转到 “数据状态” 并且释放当前的 DOCTYPE 标记;
  7. 匹配到字符 <,切换到 “标签打开状态”;
  8. 匹配到字符 h,创建一个新的起始标签标记,设置标记的标签名为空,当前状态切换至 “标签名称状态”(Tag Name State);
  9. 从字符 h 开始解析,将解析的字符一个一个添加到创建的起始标签标记的标签名中,直到匹配到字符 >,此时当前状态切换至 “数据状态”并释放当前标记,当前标记的标签名为 “html” 。
  10. 解析后续的方式与前面一致,创建并释放对应的起始标签标记,解析完毕后,当前状态处于 “数据状态” ;
  11. 匹配到字符串 “标记” ,针对每一个字符,创建并释放一个对应的字符标记,解析完毕后,当前状态仍然处于 “数据状态” ;
  12. 匹配到字符 <,进入 “标签打开状态” ;
  13. 匹配到字符 /,进入 “结束标签打开状态”(End Tag Open State);
  14. 匹配到字符 b,创建一个新的结束标签标记,设置标记的标签名为空,当前状态切换至“标签名称状态”(Tag Name State);
  15. 重新从字符 b 开始解析,将解析的字符一个一个添加到创建的结束标签标记的标签名中,直到匹配到字符 >,此时当前状态切换至 “数据状态”并释放当前标记,当前标记的标签名为 “body”;
  16. 解析 的方式与 一样;
  17. 所有的 html 标签和文本解析完成后,状态切换至“数据状态” ,一旦匹配到文件结束标志符(EOF),则释放 EOF 标记。

遇到 script 标签时的处理:

  • 内联代码:解析过程暂停,执行权转给JavaScript 脚本引擎,等待JavaScript执行完成。如果遇到调用document.write() 函数,此时渲染引擎会回到第二步,将这些代码加入字符流,重新进行解析。
  • 外链脚本:根据标签属性来执行对应的操作。

4. 构建 DOM 树

浏览器在创建解析器的同时会创建一个 Document 对象。

构建 DOM 树的步骤:

  1. 进入初始状态 “initial” 模式;
  2. 树构建器接收到 DOCTYPE 令牌后,树构建器会创建一个 DocumentType节点附加到 Document 节点上,DocumentType 节点的 name 属性为 DOCTYPE 令牌的名称,切换到“before html” 模式;
  3. 接收到令牌 html 后,树构建器创建一个 html 元素并将该元素作为 Document的子节点插入到 DOM 树中和开放元素栈中,切换为 “before head” 模式;
  4. 虽然没有接收到 head令牌,但仍然会隐式地创建 head 元素并加到 DOM 树和开放元素栈中,切换到“in head”模式;
  5. 将开放元素栈中的 head元素弹出,进入 “after head”模式;
  6. 接收到 body 令牌后,会创建一个 body 元素插入到 DOM树中同时压入开放元素栈中,当前状态切换为 “in body” 模式;
  7. 接收到字符令牌,创建 Text 节点,节点值为字符内容“标记”,将Text 节点作为 body 元素节点插入到 DOM 树中;
  8. 接收到结束令牌 body,将开放元素栈中的 body 元素弹出,切换“after body” 模式;
  9. 接收到结束令牌 html,将开放元素栈中的 html 元素弹出,切换至 “after after body” 模式;
  10. 接收到 EOF 令牌,树构建器停止构建,html 文档解析过程完成。

从 DOM 到渲染

有了 DOM 树和 CSSOM 树之后,渲染引擎就可以开始生成页面了。

5. 构建渲染树

将DOM 树包含的结构内容与 CSSOM 树包含的样式规则合并成一棵渲染树。这个过程会从 DOM 树的根节点开始遍历,然后在 CSSOM 树上找到每个节点对应的样式。

6. 布局

布局就是计算元素的大小及位置。
布局完成后会输出对应的“盒模型”,它会精确地捕获每个元素的确切位置和大小,将所有相对值都转换为屏幕上的绝对像素。

7. 绘制

绘制就是将渲染树中的每个节点转换成屏幕上的实际像素的过程。

总结

浏览器渲染引擎生成页面的 7 个步骤,前面 4 个步骤为 DOM 树的生成过程,后面 3 个步骤是利用 DOM 树和 CSSOM 树来渲染页面的过程。数据的变化过程归结如下:

字节 → 字符 → 令牌 → 树 → 页面

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章