深入理解 HTML 解析与 DOM 构建过程

VIP/

深入理解HTML解析DOM构建过程

在前端开发中,我们每天都在和HTML打交道,但你是否真正了解浏览器是如何把一串普通的HTML文本,转化为我们能交互的网页的?今天就让我们一起深入探索HTML解析与DOM构建的全过程,从底层原理出发,搞清楚这一核心机制。

一、HTML解析的前置准备:字节到字符的转换

当我们在浏览器地址栏输入一个URL并按下回车后,浏览器首先会向服务器发起请求,获取到的响应结果其实是一串二进制字节流。这一步是所有解析工作的起点,浏览器会先完成以下转换:

  1. 字节解码:浏览器根据响应头中的Content-Type字段(如text/html; charset=utf-8),或者HTML文件中的<meta charset="utf-8">标签,将二进制字节流解码为对应的字符。
  2. 字符规范化:统一不同编码格式的字符表示,确保后续解析的一致性。

二、HTML解析器的工作流程:从字符到DOM树

HTML解析器的核心任务是将字符流转换为DOM树,这是一个渐进式的过程,浏览器会一边下载HTML内容,一边进行解析,不会等到所有内容都下载完成才开始工作。

🧩 分词器:将字符拆分为Token

分词器是HTML解析的第一步,它会把输入的字符流拆分成一个个具有语义的Token,常见的Token类型包括:

  • 起始标签:如<html><div>
  • 结束标签:如</html></div>
  • 自闭合标签:如<img /><input />
  • 文本内容:如标签之间的文字
  • 注释:如<!-- 这是注释 -->

分词器会根据HTML5规范中的状态机来识别不同的Token,比如当遇到<字符时,就进入标签识别状态,当遇到>字符时,就表示一个标签Token结束。

🌳 构建器:将Token组装为DOM树

分词器生成的Token会被传递给构建器,构建器会根据Token的类型,逐步构建DOM树:

  1. 创建DOM节点:当遇到起始标签Token时,构建器会创建一个对应的DOM节点,并将其添加到DOM树中。
  2. 维护节点关系:构建器会维护一个栈结构,用来记录当前节点的层级关系。当遇到起始标签时,将对应的节点压入栈中;当遇到结束标签时,将对应的节点从栈中弹出,此时后续创建的节点就会成为弹出节点的父节点的子节点。
  3. 处理文本节点:当遇到文本Token时,构建器会创建一个文本节点,并将其添加到当前栈顶节点的子节点列表中。

举个简单的例子,对于以下HTML代码:

Html
复制
<div>
<p>Hello World</p>
</div>

构建器的工作流程如下:

  1. 遇到<div>起始标签,创建div节点,压入栈中,此时DOM树的根节点是div
  2. 遇到<p>起始标签,创建p节点,压入栈中,此时p节点成为div节点的子节点。
  3. 遇到文本Token”Hello World”,创建文本节点,添加到p节点的子节点列表中。
  4. 遇到</p>结束标签,将p节点从栈中弹出,此时栈顶节点回到div
  5. 遇到</div>结束标签,将div节点从栈中弹出,DOM树构建完成。

三、HTML解析中的特殊情况:脚本与样式的影响

在HTML解析过程中,脚本和样式的处理比较特殊,它们会影响解析的流程。

📜 脚本的阻塞特性

默认情况下,当HTML解析器遇到<script>标签时,会立即暂停解析过程,先执行脚本内容,然后再继续解析。这是因为脚本可能会修改DOM结构,比如使用document.write()方法,所以浏览器需要确保脚本执行时,前面的DOM已经构建完成。

不过,我们可以通过以下方式来优化脚本的加载和执行:

  • 异步加载:使用async属性,脚本会在后台下载,下载完成后立即执行,不会阻塞HTML解析,但执行顺序不确定。
  • 延迟加载:使用defer属性,脚本会在后台下载,等到HTML解析完成后再执行,执行顺序与脚本在HTML中的顺序一致。

🎨 样式的加载与解析

CSS样式的加载不会阻塞HTML解析,但会阻塞DOM的渲染。这是因为浏览器需要计算元素的样式,才能确定元素的最终布局和外观,如果样式还没有加载完成,浏览器会先渲染一个空白页面,等到样式加载完成后再重新渲染。

四、DOM构建完成后的后续工作

当DOM树构建完成后,浏览器还会进行以下工作:

  1. 构建CSSOM树:浏览器会解析所有的CSS样式,构建CSSOM(CSS对象模型)树。
  2. 生成渲染树:将DOM树和CSSOM树结合,生成渲染树,渲染树只包含需要显示的元素。
  3. 布局(Layout):计算每个元素在页面中的位置和大小。
  4. 绘制(Paint):将渲染树中的元素绘制到屏幕上。
  5. 合成(Composite):将绘制好的图层合成到一起,形成最终的页面。

五、深入理解的意义:优化前端性能

了解HTML解析与DOM构建的过程,对于我们优化前端性能有着重要的意义:

  • 减少阻塞:合理使用asyncdefer属性,避免脚本阻塞HTML解析。
  • 优化加载顺序:将CSS样式表放在<head>标签中,确保样式尽早加载,减少页面的白屏时间。
  • 避免重排重绘:了解DOM树的构建过程,避免在脚本中频繁修改DOM结构,减少浏览器的重排和重绘。

购买须知/免责声明
1.本文部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
2.若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
3.如果本站有侵犯、不妥之处的资源,请在网站右边客服联系我们。将会第一时间解决!
4.本站所有内容均由互联网收集整理、网友上传,仅供大家参考、学习,不存在任何商业目的与商业用途。
5.本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
6.不保证任何源码框架的完整性。
7.侵权联系邮箱:aliyun6168@gail.com / aliyun666888@gail.com
8.若您最终确认购买,则视为您100%认同并接受以上所述全部内容。

免费源码网 前端编程 深入理解 HTML 解析与 DOM 构建过程 https://svipm.com.cn/21399.html

相关文章

猜你喜欢