深入理解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树就解析完毕了
相关推荐
酷酷的阿云9 分钟前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:1379712058711 分钟前
web端手机录音
前端
齐 飞16 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
神仙别闹33 分钟前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
aPurpleBerry1 小时前
JS常用数组方法 reduce filter find forEach
javascript
GIS程序媛—椰子1 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0012 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端2 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x2 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
木舟10092 小时前
ffmpeg重复回听音频流,时长叠加问题
前端