究竟什么是DOM?

文档对象模型或“DOM”是网页的接口。 它本质上是页面的API,允许程序读取和操作页面的内容,结构和样式。

网页是如何构建的?

浏览器如何从源HTML文档转到在视口中显示样式化和交互式页面称为“关键渲染路径”。 虽然这个过程可以分解为几个步骤,正如我在“理解关键渲染路径”一文中所述,这些步骤大致可分为两个阶段。 第一阶段涉及浏览器解析文档以确定最终将在页面上呈现的内容,第二阶段涉及浏览器执行呈现。

clipboard.png

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

  1. CSSOM,与元素相关的样式的表示
  2. 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>

此文档可以表示为以下节点树:

clipboard.png

DOM不是什么?

在上面给出的示例中,看起来DOM是源HTML文档的一对一映射或您看到的DevTools的映射。 但是,正如我所提到的,存在差异。 为了完全理解DOM是什么,我们需要看看它不是什么。

DOM不是您的源HTML

尽管DOM是从源HTML文档创建的,但它并不总是完全相同。 有两个实例,DOM可以与源HTML不同。

  1. 当HTML无效时

DOM是有效HTML文档的接口。 在创建DOM的过程中,浏览器可以纠正HTML代码中的一些无效。

我们以此HTML文档为例:

<!doctype html>
<html>
Hello, world!
</html>

该文档缺少<head><body>元素,这是有效HTML的要求。 如果我们查看生成的DOM树,我们将看到这已得到纠正:

clipboard.png

  1. 当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>元素:

clipboard.png

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

clipboard.png

DOM不是DevTools中的东西

这种差异有点小,因为DevTools元素检查器提供了我们在浏览器中最接近的DOM。 但是,DevTools检查器包含不在DOM中的其他信息。

最好的例子是CSS伪元素。 使用::before::after选择器创建的伪元素构成CSSOM和渲染树的一部分,但在技术上不是DOM的一部分。 这是因为DOM仅由源HTML文档构建,不包括应用于元素的样式。

尽管伪元素不是DOM的一部分,但它们仍在我们的devtools元素检查器中。

clipboard.png

这就是为什么伪元素不能被Javascript作为目标的原因,因为它们不是DOM的一部分。

概括

DOM是HTML文档的接口。 它被浏览器用作确定在视口中呈现内容的第一步,并通过Javascript程序来修改页面的内容,结构或样式。

虽然与其他形式的源HTML文档类似,但DOM在许多方面有所不同:

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

创建了一个程序员交流微信群,大家进群交流IT技术

图片描述

如果已过期,可以添加博主微信号15706211347,拉你进群


优质翻译文章
优质翻译文章

前端开发者

4.5k 声望
1.3k 粉丝
0 条评论
推荐阅读
webpack构建速度优化
使用webpack.DllPlugin优化,其实并没有优化速度,只是把一些不需要经常变更的部分提前构建,之后只需要构建变更的部分就可以了,确实优化了时间

frontoldman9阅读 2.8k评论 4

「多图预警」完美实现一个@功能
一天产品大大向 boss 汇报完研发成果和产品业绩产出,若有所思的走出来,劲直向我走过来,嘴角微微上扬。产品大大:boss 对我们的研发成果挺满意的,balabala...(内心 OS:不听,讲重点)产品大大:咱们的客服 I...

wuwhs32阅读 3.5k评论 5

封面图
还在用 JS 做节流吗?CSS 也可以防止按钮重复点击
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候我想大部分同学都会到网上直接拷贝一段throttle函数,或者直接引用lodash工具库

XboxYan35阅读 2.7k评论 2

封面图
CSS transition 小技巧!如何保留 hover 的状态?
欢迎关注我的公众号:前端侦探通常情况下,hover 是无法保存状态的。鼠标移入触发额外样式,一旦移出就还原了 {代码...} 这就意味着,如果需要保留hover的状态,可能就不得不借助JS了,比如下面是某某书院的首页...

XboxYan30阅读 3.9k评论 2

封面图
CSS 如何设置自动滚动定位的“安全”间距?
欢迎关注我的公众号:前端侦探介绍两个和滚动定位相关的 CSS 属性:scroll-padding和 scroll-margin在平时开发中,经常会碰到需要快速定位的问题,比如常见的锚点定位 {代码...} 这样,在点击a标签时会自动定位到...

XboxYan31阅读 2.5k评论 2

封面图
【已结束】SegmentFault 思否写作挑战赛!
SegmentFault 思否写作挑战赛 是思否社区新上线的系列社区活动在 2 月 8 日 正式面向社区所有用户开启;挑战赛中包含多个可供作者选择的热门技术方向,根据挑战难度分为多个等级,快来参与挑战,向更好的自己前进!

SegmentFault思否20阅读 5.1k评论 10

封面图
由小见大!不规则造型按钮解决方案
今天,有个群友在群里提问,使用 CSS 能否实现下述这个图形:emmm,中间这个酷似三次贝塞尔曲线的造型,使用 CSS 不太好实现。我的建议是切图实现,然而群友要求一定要用 CSS 实现。虽然麻烦,但是这个图形勉强也...

chokcoco17阅读 1.3k

封面图

前端开发者

4.5k 声望
1.3k 粉丝
宣传栏