究竟什么是DOM?

44次阅读

共计 2021 个字符,预计需要花费 6 分钟才能阅读完成。

文档对象模型或“DOM”是网页的接口。它本质上是页面的 API,允许程序读取和操作页面的内容,结构和样式。
网页是如何构建的?
浏览器如何从源 HTML 文档转到在视口中显示样式化和交互式页面称为“关键渲染路径”。虽然这个过程可以分解为几个步骤,正如我在“理解关键渲染路径”一文中所述,这些步骤大致可分为两个阶段。第一阶段涉及浏览器解析文档以确定最终将在页面上呈现的内容,第二阶段涉及浏览器执行呈现。

第一阶段的结果是所谓的“渲染树”。渲染树是将在页面上呈现的 HTML 元素及其相关样式的表示。为了构建这个树,浏览器需要两件事:

CSSOM,与元素相关的样式的表示
DOM,元素的表示

如何创建 DOM(以及它看起来像什么)?
DOM 是源 HTML 文档的基于对象的表示。它有一些差异,我们将在下面看到,但它本质上是一种尝试将 HTML 文档的结构和内容转换为可供各种程序使用的对象模型。
DOM 的对象结构由所谓的“节点树”表示。它之所以被称为是因为它可以被认为是具有单个父茎的树,其分枝成几个子枝,每个子枝可以具有叶子。在这种情况下,父“stem”是根 <html> 元素,子“branches”是嵌套元素,“leaves”是元素中的内容。
我们以此 HTML 文档为例:
<!doctype html>
<html lang=”en”>
<head>
<title>My first web page</title>
</head>
<body>
<h1>Hello, world!</h1>
<p>How are you?</p>
</body>
</html>
此文档可以表示为以下节点树:

DOM 不是什么?
在上面给出的示例中,看起来 DOM 是源 HTML 文档的一对一映射或您看到的 DevTools 的映射。但是,正如我所提到的,存在差异。为了完全理解 DOM 是什么,我们需要看看它不是什么。
DOM 不是您的源 HTML
尽管 DOM 是从源 HTML 文档创建的,但它并不总是完全相同。有两个实例,DOM 可以与源 HTML 不同。
当 HTML 无效时
DOM 是有效 HTML 文档的接口。在创建 DOM 的过程中,浏览器可以纠正 HTML 代码中的一些无效。
我们以此 HTML 文档为例:
<!doctype html>
<html>
Hello, world!
</html>
该文档缺少 <head> 和 <body> 元素,这是有效 HTML 的要求。如果我们查看生成的 DOM 树,我们将看到这已得到纠正:

当 Javascript 修改 DOM 时
除了作为查看 HTML 文档内容的界面之外,还可以修改 DOM,使其成为活动的资源。
例如,我们可以使用 Javascript 为 DOM 创建其他节点。
var newParagraph = document.createElement(“p”);
var paragraphContent = document.createTextNode(“I’m new!”);
newParagraph.appendChild(paragraphContent);
document.body.appendChild(newParagraph);
这将更新 DOM,但当然不是我们的 HTML 文档。
DOM 不是您在浏览器中看到的(即渲染树)
您在浏览器视口中看到的是渲染树,正如我所提到的,它是 DOM 和 CSSOM 的组合。真正将 DOM 与渲染树分开的是,后者只包含最终将在屏幕上绘制的内容。
因为渲染树仅关注渲染的内容,所以它会排除视觉上隐藏的元素。例如,具有 display:none 的样式。
<!doctype html>
<html lang=”en”>
<head></head>
<body>
<h1>Hello, world!</h1>
<p style=”display: none;”>How are you?</p>
</body>
</html>
DOM 将包含 <p> 元素:

但是,渲染树以及因此在视口中看到的内容将不包含该元素。

DOM 不是 DevTools 中的东西
这种差异有点小,因为 DevTools 元素检查器提供了我们在浏览器中最接近的 DOM。但是,DevTools 检查器包含不在 DOM 中的其他信息。
最好的例子是 CSS 伪元素。使用::before 和::after 选择器创建的伪元素构成 CSSOM 和渲染树的一部分,但在技术上不是 DOM 的一部分。这是因为 DOM 仅由源 HTML 文档构建,不包括应用于元素的样式。
尽管伪元素不是 DOM 的一部分,但它们仍在我们的 devtools 元素检查器中。

这就是为什么伪元素不能被 Javascript 作为目标的原因,因为它们不是 DOM 的一部分。
概括
DOM 是 HTML 文档的接口。它被浏览器用作确定在视口中呈现内容的第一步,并通过 Javascript 程序来修改页面的内容,结构或样式。
虽然与其他形式的源 HTML 文档类似,但 DOM 在许多方面有所不同:

它总是有效的 HTML
它是一个可以通过 Javascript 修改的活模型
它不包含伪元素(例如::after)
它确实包含隐藏元素(例如 display: none)

正文完
 0