一、什么是DOM
DOM(Document Object Model) 文档对象模型,是HTML和XML文档的编程接口
- DOM 以树结构表达 HTML 文档,树的每个分支的终点都是一个节点,每个节点都包含着对象
- DOM 将web页面与脚本或编程语言链接起来,可以通过DOM提供的方法改变节点的结构、样式或者内容。
二、为什么要介绍DOM树?
DOM树是浏览器标记内部的表示,浏览器接收到网络数据后的第一步就是 处理HTML标记并构建DOM树。
三、DOM树的构建
- DOM树是一种有限层次的树结构,树顺序由HTML文档决定的
- 参与树的最小单位是对象(节点),如果该对象的父对象(父节点)为null,那么该对象(节点)就是DOM树的根;对象可以具有子对象(子节点),这是一个有序的对象集
通过菜鸟教程的一张图片来分析一下DOM树
- Document 根节点(有些文档说Document是根节点,也有些文档说 html元素是 根节点。从对象的角度上来看,Document是根对象,从元素的角度上看,html元素由于父元素是null,所以是根元素);
- html 元素,html元素的父元素为null,所以从元素的角度来说是树的根;
- head 元素 和 body 元素 都是 html 根元素的子元素。所以树对象(节点)可以具有子对象(子节点);
- href属性 是 a 元素的子对象(子节点),所以DOM树包含属性对象(属性节点);
- text文本 是 title元素 的子对象(子节点),所以DOM树包含文本对象(文本节点);
- a元素 的 父对象 是 body元素,body元素的 父对象 是 html元素,所以html元素 是 a元素的祖先对象(祖先节点);
- a元素 和 h1元素 都是 body元素的子对象(子节点),所以 a元素 和 h1元素是兄弟对象(兄弟节点);
- 图中没有提到 注释节点,但是注释也是DOM树的一部分;
四、怎么解析文档从而构建DOM树
- 解析的过程可以分成两个子进程:词法分析和语法分析
- 词法分析是将输入内容分割成大量标记(如:html、body等)的过程。标记是语言中的词汇,构成内容的基本单位。
- 语法分析是引用语言的语法规则的过程(如html 超文本标记语言)。
- 词法分析器(又称标记生成器),负责将输入的文档内容分解成一个个有效标记,然后解析器负责根据语言(html)语法规则分析文档的结构,从而构建解析树(DOM树)。
4-1 词法分析器
<html>
<body>
<p>Hello world</p>
</body>
</html>
- 初始化是数据状态
- 遇到 < 字符时,将状态改成“标记打开状态”
- 然后接收 a-z或A-Z字符就会创建“起始标记”,状态变成“标记名称状态”
- 然后直到接收到 > 字符,在标记名状态期间接受的每个字符都会附加到新的标记名称上(如上述代码中的html)
- 接收到 > 字符,会发送当前的标记,状态改成“数据状态”
- body 和 p 都会执行上面 4 个步骤。
- 接收 Hello world 中的 H 字符时,将创建并发送字符标记,直到接收到 </p> 的 < 字符,在这个过程中每个字符都会发送一个字符标记
- 接收到 < 字符就又回到 “标记打开状态”
- 当在 “标记打开状态”接收到 / 字符时,会创建 end tag token,并将状态改为“标记名称状态”,后面就跟上述一样了。
4-2 树的构建
- 创建解析器的同时,会创建Document对象。
- 词法分析器(标记生成器)发送的每个节点都会由树构建器进行处理,并添加到DOM树上
- 在添加到DOM树的同时还会添加到开发元素的堆栈中(用来纠正嵌套错误和处理未关闭的标记)
树构建阶段输入的是一个来自标记化阶段的标记序列
- 初始模式“initial mode”
- 接收到HTML标记后转成“before html”模式,并处理html标记,创建HTMLHtmlElement元素,并将其添加到Document对象上
- 然后将状态改成“before head”,按照上面的示例此时应该接收到“body”标记,如果没有接收到head标记,系统会隐式创建一个HTMLHeadElement元素,并添加到树中
- 然后进入“in head”,然后转为“after head”模式。此时系统才会对“body”标记尽进行处理,并创建HTMLBodyElement元素,同时进入“in body”模式
- 然后接收 p 标记 进入“in p”状态,并同时创建HTMLParagraphElement元素。
- 接收到由“Hello world”字符串生成的一系列字符标记。接收到第一个字符时会创建并插入“Text”节点,其他字符会附加到这个节点上。
- 然后接收p结束标记转成“after p”模式,然后收到body结束标签转成“after body”模式
- 接收到HTML结束标记时会进入“after after body”模式。解析过程也就到此结束了。