深入理解DOM:从标签到树,解析HTML的奥秘

什么是DOM

DOM是文档对象模型(Document Object Model)的缩写,是一种用于表示和操作HTML、XML等文档结构的编程接口。DOM 将文档解析成一个由层层嵌套的节点组成的树形结构,每个节点代表文档中的一个元素、属性、文本等。

Web开发中,通常指的是HTML文档的DOMHTML文档的DOM模型呈现为一个树状结构,树的每个节点表示文档中的一个元素,如段落、标题、链接等。通过DOM,开发者可以使用编程语言(如JavaScript)来操作文档的结构、内容和样式,实现动态的页面效果和交互。

DOM 提供了一组API,通过这些API,开发者可以:

  1. 访问文档的元素,属性和文本内容。
  2. 修改文档的结构、样式和内容。
  3. 添加、删除或替换文档中的元素。
  4. 对文档中的事件进行监听和响应。

JavaScript中,可以通过以下方式获取DOM

  • 使用 document 对象: document 对象代表整个HTML文档,开发者可以通过它访问文档中的元素、属性等。
  • 使用 DOM API 通过 DOM 提供的一系列方法和属性,可以对文档进行操作和查询。

从页面视角看DOM

  • 页面结构: DOM 表示网页的结构,将 HTML 文档解析成一个树形结构,每个节点代表文档中的一个元素、属性、文本等。通过DOM,页面的结构可以被JavaScript脚本访问和修改。
  • 动态更新: JavaScript通过DOM可以实现动态更新页面,例如添加、删除、或修改元素,改变样式,更新内容等。这使得网页能够根据用户的交互和动态数据进行实时更新。
html 复制代码
<html>
    <head>
        <title>DOM示例</title>
    </head>
    <body>
        <div id="example">Hello, DOM!</div>
        <script>
            // JavaScript脚本通过DOM修改页面内容
            document.getElementById('example').innerHTML = 'Hello, Updated DOM!';
        </script>
    </body>
</html>

JavaScript脚本视角看DOM

  • 编程接口: DOM 提供了一种编程接口,允许JavaScript通过操作DOM来与页面进行交互。开发者可以使用一系列的方法和属性来查询、修改、删除文档中的元素。
  • 事件处理: DOM 允许JavaScript通过事件处理器来监听和响应页面上的事件,如点击、鼠标移动、键盘输入等。这使得页面能够对用户的交互做出响应。
js 复制代码
// JavaScript脚本通过DOM添加事件处理器
document.getElementById('example').addEventListener('click', function () {
    alert('Element Clicked!');
});

从安全视角看DOM

  • 跨站脚本攻击(XSS): 操作DOM时,需要注意防范XSS攻击,不要直接使用用户输入来进行DOM操作,而应使用安全的DOM操作方法,以防止恶意脚本的执行。
  • 内容安全策略(CSP): CSP是一种通过定义规则,限制页面中资源加载和脚本执行的安全机制。它可以防止不受信任的脚本执行,增加网页的安全性。
  • 点击劫持(Clickjacking): 可以通过DOM操作来检测和防范点击劫持攻击,确保页面不被嵌套在恶意框架中。

DOM树如何生成

DOM(文档对象模型)树是浏览器将 HTML 文档解析后所形成的一种树状结构,表示了文档的层次结构和元素之间的关系。

  1. HTML 解析: 当浏览器加载一个页面时,它首先会通过网络请求获取 HTML 文件。浏览器通过解析 HTML 文档来理解页面的结构和内容。HTML 解析器会逐行读取 HTML 文件,将其分解为一系列的标记(标签、属性、文本等)。
  2. Tokenization(词法分析): HTML 解析器会将 HTML 文档分解为一系列的标记(Tokens)。这个过程称为词法分析。标记是 HTML 文档中的最小单元,可以是开始标签、结束标签、属性、文本等。
  3. 构建节点对象: 解析器根据这些标记构建出一个节点对象的树形结构,这个树就是 DOM 树。每个标记被转化为一个节点对象,节点对象包括元素节点、文本节点、注释节点等。
  4. 构建父子关系: 根据标记之间的嵌套关系,构建父子关系,形成树状结构。开始标签和结束标签之间的内容成为该元素节点的子节点。嵌套的层次关系会被反映在生成的 DOM 树中。
  5. DOM 树完成: 一旦解析器完成对整个 HTML 文档的解析和节点对象的构建,就形成了完整的 DOM 树。这个树包含了 HTML 文档中的所有元素、属性和文本节点,以及它们之间的层次结构和关系。
html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>DOM树生成示例</title>
</head>
<body>
    <h1>Hello, DOM!</h1>
    <p>This is a simple example.</p>
</body>
</html>

生成的 DOM 树大致结构如下:

markdown 复制代码
- Document
  - html
    - head
      - title
        - Text: "DOM树生成示例"
    - body
      - h1
        - Text: "Hello, DOM!"
      - p
        - Text: "This is a simple example."

Token栈

HTML 解析过程中, HTML 解析器会维护一个token栈token 栈的维护是解析器用来跟踪当前状态和构建 DOM 树的关键部分。Token 栈存储了从 HTML 文档中提取的标记(tokens)。解析器根据这些标记进行分析,同时将节点对象构建成 DOM 树的结构。

以下是token栈的维护过程

  1. 栈的初始化: 解析器在开始解析时初始化一个空的 token 栈。这个栈用于跟踪当前解析的状态,并在构建 DOM 树时维护层次结构。
  2. 处理开始标签: 当解析器遇到开始标签时,它会创建一个元素节点对象,并将这个节点推入 token 栈。同时,当前元素节点成为新的活动元素,用于后续的构建。
  3. 处理文本和属性: 文本和属性也被解析成相应的标记,解析器可能会将它们添加到当前活动元素节点或者在 token 栈中进行适当的处理。例如,将文本添加到当前元素节点的子节点中,将属性添加到当前元素节点的属性列表中。
  4. 处理结束标签: 当解析器遇到结束标签时,它会弹出 token 栈的栈顶元素。这表示当前元素的构建已经完成,并且当前活动元素将回退到上一个元素。结束标签通常会触发栈的出栈操作。

DOM树生成图示

用这段代码讲解DOM树是如何生成的

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>DOM树生成示例</title>
</head>
<body>
    <h1>Hello, DOM!</h1>
    <div>
        <p>1</p>
        <p>2</p>
    </div>
    <div>
        <p>3</p>
    </div>
</body>
</html>
  1. 首先HTML解析器开始工作时,会默认创建一个根为document的空DOM树结构,同时会把第一个开始标签的token压入栈底,并创建该DOM节点加入DOM树种
  1. 然后就是解析出head开始标签和title开始标签

  2. 下来是title标签的文本节点

  1. 此时解析到title的结束标签,将token栈中的title的开始标签弹出栈
  1. 同样接下来遇到head的结束标签,将head的开始标签弹出栈 如图所示
  1. 接下来解析到body的开始标签,压入栈中
  1. 接下来是h1的开始标签
  1. 依次解析到html结束标签前dom树和token栈如图所示
  1. 最后 遇到html的结束标签继续弹出栈,直到token栈清空,这个DOM树就解析完毕了
相关推荐
哆啦A梦158817 分钟前
商城后台管理系统 03 登录布局
javascript·vue.js·elementui
曼巴UE541 分钟前
UE FString, FName ,FText 三者转换,再次学习,官方文档理解
服务器·前端·javascript
selt7911 小时前
Redisson之RedissonLock源码完全解析
android·java·javascript
行走的陀螺仪1 小时前
高级前端 Input 公共组件设计方案(Vue3 + TypeScript)
前端·javascript·typescript·vue·组件设计方案
一颗不甘坠落的流星2 小时前
【Antd】基于 Upload 组件,导入Json文件并转换为Json数据
前端·javascript·json
LYFlied2 小时前
Vue2 与 Vue3 虚拟DOM更新原理深度解析
前端·javascript·vue.js·虚拟dom
Lucky_Turtle2 小时前
【Node】npm install报错npm error Cannot read properties of null (reading ‘matches‘)
前端·npm·node.js
小飞侠在吗2 小时前
vue shallowRef 与 shallowReacitive
前端·javascript·vue.js
惜分飞3 小时前
sql server 事务日志备份异常恢复案例---惜分飞
前端·数据库·php