HTML 文档的主干是标签。
根据文档对象模型 (DOM),每个 HTML 标签都是一个对象。嵌套标签是封闭标签的“子级”。标签内的文本也是一个对象。
所有这些对象都可以使用 JavaScript 访问,我们可以使用它们来修改页面。
例如,document.body
是表示 <body>
标签的对象。
运行此代码会使 <body>
在 3 秒钟内变为红色
document.body.style.background = 'red'; // make the background red
setTimeout(() => document.body.style.background = '', 3000); // return back
这里我们使用 style.background
更改 document.body
的背景颜色,但还有许多其他属性,例如
innerHTML
– 节点的 HTML 内容。offsetWidth
– 节点宽度(以像素为单位)- …等等。
我们很快就会学习更多操作 DOM 的方法,但首先我们需要了解其结构。
DOM 的示例
让我们从以下简单的文档开始
<!DOCTYPE HTML>
<html>
<head>
<title>About elk</title>
</head>
<body>
The truth about elk.
</body>
</html>
DOM 将 HTML 表示为标签的树结构。如下所示
在上面的图片中,你可以单击元素节点,它们的子节点将打开/折叠。
每个树节点都是一个对象。
标签是元素节点(或仅仅是元素),并形成树结构:<html>
在根部,然后 <head>
和 <body>
是它的子节点,等等。
元素内的文本形成文本节点,标记为 #text
。文本节点仅包含一个字符串。它可能没有子节点,并且始终是树的叶子。
例如,<title>
标签的文本是 "关于 elk"
。
请注意文本节点中的特殊字符
- 换行符:
↵
(在 JavaScript 中称为\n
) - 空格:
␣
空格和换行符是完全有效的字符,就像字母和数字一样。它们形成文本节点并成为 DOM 的一部分。因此,例如,在上面的示例中,<head>
标签在 <title>
之前包含一些空格,并且该文本成为 #text
节点(它仅包含换行符和一些空格)。
只有两个顶级排除项
- 由于历史原因,
<head>
之前的空格和换行符被忽略。 - 如果我们在
</body>
之后放置一些内容,那么它将根据 HTML 规范自动移动到body
内部,在末尾,因为所有内容都必须在<body>
内。因此,</body>
之后不能有任何空格。
在其他情况下,一切都非常简单——如果文档中存在空格(就像任何字符一样),那么它们将成为 DOM 中的文本节点,如果我们删除它们,那么将不会有任何空格。
这里没有仅空格的文本节点
<!DOCTYPE HTML>
<html><head><title>About elk</title></head><body>The truth about elk.</body></html>
通常使用 DOM 的浏览器工具(很快将介绍)不会显示文本开头/结尾处的空格和标签之间的空文本节点(换行符)。
开发者工具通过这种方式节省屏幕空间。
在进一步的 DOM 图片中,当它们不相关时,我们有时会省略它们。此类空格通常不会影响文档的显示方式。
自动更正
如果浏览器遇到格式错误的 HTML,它会在生成 DOM 时自动更正它。
例如,最上面的标签始终是 <html>
。即使它不存在于文档中,它也会存在于 DOM 中,因为浏览器会创建它。<body>
也一样。
例如,如果 HTML 文件是单个单词 "Hello"
,浏览器会将其包装到 <html>
和 <body>
中,并添加必需的 <head>
,并且 DOM 将是
在生成 DOM 时,浏览器会自动处理文档中的错误、关闭标签等。
带有未关闭标签的文档
<p>Hello
<li>Mom
<li>and
<li>Dad
…当浏览器读取标记并恢复缺失部分时,将变成一个正常的 DOM
<tbody>
表格是一个有趣的“特例”。根据 DOM 规范,它们必须具有 <tbody>
标记,但 HTML 文本可以省略它。然后,浏览器会自动在 DOM 中创建 <tbody>
。
对于 HTML
<table id="table"><tr><td>1</td></tr></table>
DOM 结构将是
看到了吗?<tbody>
凭空出现了。在处理表格时,我们应该记住这一点,以避免意外。
其他节点类型
除了元素和文本节点之外,还有一些其他节点类型。
例如,注释
<!DOCTYPE HTML>
<html>
<body>
The truth about elk.
<ol>
<li>An elk is a smart</li>
<!-- comment -->
<li>...and cunning animal!</li>
</ol>
</body>
</html>
我们可以在此看到一个新的树节点类型——注释节点,标记为 #comment
,位于两个文本节点之间。
我们可能会想——为什么将注释添加到 DOM?它不会以任何方式影响可视化表示。但有一条规则——如果 HTML 中有内容,那么它也必须在 DOM 树中。
HTML 中的一切,甚至是注释,都成为 DOM 的一部分。
即使是 HTML 最开始的 <!DOCTYPE...>
指令也是一个 DOM 节点。它在 DOM 树中位于 <html>
之前。很少有人知道这一点。我们不会触及该节点,我们甚至不会在图表中绘制它,但它就在那里。
形式上,表示整个文档的 document
对象也是一个 DOM 节点。
有 12 种节点类型。在实践中,我们通常使用其中的 4 种
document
——进入 DOM 的“入口点”。- 元素节点——HTML 标记,树构建块。
- 文本节点——包含文本。
- 注释——有时我们可以将信息放在那里,它不会显示,但 JS 可以从 DOM 中读取它。
自己看看
要实时查看 DOM 结构,请尝试使用 实时 DOM 查看器。只需在文档中输入,它就会立即显示为 DOM。
探索 DOM 的另一种方法是使用浏览器开发者工具。实际上,这是我们在开发时使用的工具。
为此,请打开网页 elk.html,打开浏览器开发者工具并切换到“元素”选项卡。
它应该如下所示
你可以看到 DOM,单击元素,查看它们的详细信息等等。
请注意,开发者工具中的 DOM 结构已简化。文本节点仅显示为文本。并且根本没有“空白”(仅空格)文本节点。这很好,因为大多数时候我们对元素节点感兴趣。
单击左上角的 按钮,我们可以使用鼠标(或其他指针设备)从网页中选择一个节点并“检查”它(在“元素”选项卡中滚动到它)。当我们有一个巨大的 HTML 页面(以及相应的巨大 DOM)并希望看到其中特定元素的位置时,这非常有用。
另一种方法是右键单击网页并在上下文菜单中选择“检查”。
在工具的右侧有以下子选项卡
- 样式 – 我们可以逐条规则地查看应用于当前元素的 CSS,包括内置规则(灰色)。几乎所有内容都可以就地编辑,包括下方框的尺寸/边距/内边距。
- 已计算 – 按属性查看应用于元素的 CSS:对于每个属性,我们可以看到提供该属性的规则(包括 CSS 继承等)。
- 事件侦听器 – 查看附加到 DOM 元素的事件侦听器(我们将在本教程的下一部分中介绍它们)。
- …等等。
研究它们的最佳方法是四处点击。大多数值都可以就地编辑。
与控制台交互
在处理 DOM 时,我们可能还想对其应用 JavaScript。例如:获取一个节点并运行一些代码来修改它,以查看结果。以下是几个在元素选项卡和控制台之间切换的技巧。
首先
- 在元素选项卡中选择第一个
<li>
。 - 按 Esc – 它将在元素选项卡正下方打开控制台。
现在,最后选择的元素可用作 $0
,之前选择的元素可用作 $1
等。
我们可以在它们上运行命令。例如,$0.style.background = 'red'
使选定的列表项变为红色,如下所示
这就是在控制台中从元素获取节点的方法。
还有一条返回路径。如果有一个引用 DOM 节点的变量,那么我们可以在控制台中使用命令 inspect(node)
在元素窗格中查看它。
或者,我们只需在控制台中输出 DOM 节点并探索“就地”,如下面的 document.body
当然,这是为了调试目的。从下一章开始,我们将使用 JavaScript 访问和修改 DOM。
浏览器开发者工具在开发中提供了极大的帮助:我们可以探索 DOM,尝试一些操作并查看出了什么问题。
总结
HTML/XML 文档在浏览器中表示为 DOM 树。
- 标签变为元素节点并形成结构。
- 文本变为文本节点。
- …等,HTML 中的任何内容在 DOM 中都有其位置,甚至注释也是如此。
我们可以使用开发者工具来检查 DOM 并手动修改它。
在这里,我们介绍了基础知识,即最常用和最重要的入门操作。在 https://developers.google.com/web/tools/chrome-devtools 上有关于 Chrome 开发者工具的详尽文档。学习这些工具的最佳方法是单击此处和那里,阅读菜单:大多数选项都很明显。稍后,当你大致了解它们时,阅读文档并了解其余内容。
DOM 节点具有属性和方法,允许我们在它们之间穿行、修改它们、在页面上移动,等等。我们将在下一章中详细了解它们。
评论
<code>
标记,对于多行 - 将它们包装在<pre>
标记中,对于超过 10 行 - 使用沙箱 (plnkr,jsbin,codepen…)