本文为翻译,若有异议请提出更正建议,欢迎阅读。javascript
做者:Ire Aderinokunhtml
原文地址:What, exactly, is the DOM?java
文档对象模型,或“DOM”,是web页面的接口。它本质上是页面的API,容许程序读取和操做页面的内容、结构和样式。让咱们分解一下。web
浏览器如何从一个源HTML文档到在视图中显示一个样式化的交互式页面被称为“关键呈现路径”。虽然这个过程能够分解为几个步骤,但正如我在理解关键呈现路径的文章中所述,这些步骤大体能够分为两个阶段。第一个阶段涉及浏览器解析文档以肯定最终在页面上呈现什么,第二个阶段涉及浏览器执行呈现。 浏览器
第一阶段的结果是所谓的“渲染树”。渲染树是将在页面上呈现的HTML元素及其相关样式的表示。为了构建这个树,浏览器须要两件事:app
DOM是源HTML文档的基于对象的表示。正如咱们将在下面看到的,它有一些不一样之处,但它本质上是试图将HTML文档的结构和内容转换为可由各类程序使用的对象模型。dom
DOM的对象结构由所谓的“节点树”表示。之因此这样叫它,是由于它能够被认为是一棵树,它有一个单一的父茎,它能够分出几个子枝,每一个子枝均可能有叶子。在本例中,父“茎”是根元素,子“分支”是嵌套的元素,而“叶”是元素中的内容。ui
咱们以此HTML文档为例:spa
<!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彷佛是源HTML文档或您所看到的DevTools的一对一映射。可是,正如我所提到的,有一些区别。为了彻底理解DOM是什么,咱们须要了解它不是什么。
虽然DOM是从源HTML文档建立的,但它并不老是彻底相同。在两个实例中,DOM能够与源HTML不一样。
DOM是有效HTML文档的接口。在建立DOM的过程当中,浏览器可能会纠正HTML代码中的一些错误。
让咱们以这个HTML文档为例:
<!doctype html>
<html>
Hello, world!
</html>
复制代码
文档缺乏一个<head>
和<body>
元素,这是有效HTML的一个要求。若是咱们查看生成的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和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>
元素:
然而,渲染树,以及在视图中看到的内容,将不包含该元素。
这种差别有点小,由于DevTools元素检查器提供了与浏览器中DOM最接近的近似。可是,DevTools检查器包含了不在DOM中的其余信息。
最好的例子是CSS伪元素。使用::before
和::after
选择器建立的伪元素构成CSSOM和渲染树的一部分,但在技术上不是DOM的一部分。这是由于DOM是单独从源HTML文档构建的,不包括应用于元素的样式。
尽管伪元素不是DOM的一部分,可是它们在咱们的devtools元素检查器中。
这就是Javascript不能以伪元素为目标的缘由,由于它们不是DOM的一部分。
DOM是HTML文档的接口。浏览器使用它做为决定在视图中呈现什么内容的第一步,并经过Javascript程序修改页面的内容、结构或样式。
虽然与源HTML文档的其余形式相似,DOM在许多方面是不一样的:
::after
)display: none
)