DOM tree (文档翻译)
DOM tree
HTML文档的脊背是标签(tags)。
根据文档对象模型(DOM),每个HTML标签都是一个对象(object)。嵌套的标签是封闭标签的子集。标签内的文本也是一个对象。
所有的这些对象都可通过JavaScript访问,我们可以用它们来修改页面。
举个例子,document.body
是<body>
标签的对象。
运行以下的代码会使<body>
变红3秒。
document.body.style.background = 'red'; //使背景变红
setTimeout(()=>document.body.style.background = '',3000); // 撤销上一步
这里我们用了style.background
属性来修改document.body
的背景色。除此之外,还有许多其他的属性,例如:
innerHTML
- 节点的HTML内容。offsetWidth
- 节点的宽度(像素值)- ...
DOM的一个例子
让我们从下面这个简单的文档开始:
<!DOCTYPE HTML>
<html>
<head>
<title>About elk</title>
</head>
<body>
The truth about elk.
</body>
</html>
DOM将HTML表示为标签的树型结构(tree structure)。看上去就是:
在上面的图片中,你可以点击元素节点(element nodes)来控制它的子节点的展开或收缩。(原文可以,此处为图片)
每一个树节点都是一个对象。
标签是元素节点(或仅仅是元素),并形成树结构:<html>
在根位置,<head>
和<body>
是它的孩子,以此类推。
元素内部的文本代表了一个文本节点,标记为#text
。一个文本节点仅包含了一个字符串。它可能没有孩子,且总在树的叶子位置。
例如,<title>
内标签有文本为"About elk"
。
在文本节点中,要注意一些特殊字符:
- 转行符:
↵
(在JavaScript中称为\n
) - 空格符:
␣
空格符和转行符是和字母与数字一样有效的字符。它们组成了文本节点并成为了DOM的一部分。例如在上面的那个例子中,<head>
标签在<title>标签前
还包含了一些空格符,并且该文本成为了一个#text
节点(它仅包含了一个转行符和一些空格符)。
这里有两个优先排除项:
- 由于一些历史原因,
<head>
标签之前的空格符和转行符被忽略了。 - 如果我们在
<body>
标签后放置一些东西,在最后它会被自动转移到<body>
内部。HTML规范要求所有的内容都必须放在<body>
标签的内部,所以<body>
后面不能有任何空格。
除此之外的一切都很简单 - 如果文档中有空格(就像其它任意字符一样),它们就会变成DOM中的文本节点。删除后便不复存在。
下面是没有空格 - 仅包含文本的节点:
<!DOCTYPE HTML>
<html><head><title>About elk</title></head><body>The truth about elk.</body></html>
⚠️字符串开始或结尾的空格以及只有空格的文本节点通常会被隐匿在工具里
与DOM一起使用的浏览器工具(即将介绍)通常不会显示文本开头或结尾的空格,也不会显示标签之间的空白文本节点(换行符)。
开发者工具可以通过这种方式节省屏幕空间。
在其它的DOM图片上我们有时会忽略他们。这样的空格通常不会影响到文档的显示方式。
自动修正(Autocorrection)
如果浏览器遇到格式错误的HTML,则会在生成DOM时自动修正它。
例如,最开始的标签总是<html>
。即使它不在文档中存在,它也会在DOM中存在,因为浏览器会自动生成。同样的也适用于<body>
。
举一个例子,如果一个HTML文件只有一个单词"hello"
,浏览器会把它包装为<html>
和<body>
,并添加必要的<head>
,然后DOM就会变成:
当生成DOM时,浏览器会自动处理文档中的错误,闭合标签等。
一个存在未闭合标签的文档如:
<p>Hello
<li>Mom
<li>and
<li>Dad
...会在浏览器读取标签和恢复丢失的部分后变成一个普通的DOM:
⚠️表单(Table)永远拥有
<tbody>
标签在表格中有一个有趣的“特殊案例”。根据DIOM规范,表格必须拥有
<tbody>
标签,但HTML文本可以(正式的)将其省略。然后浏览器会在DOM中自动的生成<tbody>
。HTML文件:
<table id="table"><tr><td>1</td></tr></table>
DOM结构将为:
看到了吗?
<tbody>
突然出现。你应当时时记住这一点,防止在使用时出现意外。
其它节点类型
除了元素和文本节点外还有其它节点类型。
例如,注释节点(comments):
<!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>
标签之前。我们不会接触那个节点,甚至因此不在图表里绘制它,但它就在那里。
表示整个文档的documnet
对象在形式上也是DOM节点。
共有12种节点类型,在练习中我们通常使用这四个:
document
- DOM的"入口"- 元素节点 - HTML标签,树的构建模块
- 文本节点 - 包含文本
- 注释 - 有时我们会里放一些信息,它不会显示,但是JS能够从DOM中读取到
自己看看
要实时查看DOM结构,可以尝试Live DOM Viewer。只要在文档中输入,它就会即时显示为DOM。
探索DOM的另一种方式是使用浏览器的开发者工具。事实上,这才是我们在开发中所使用到的。
为此,请打开网页elk.html,再打开浏览器的开发者工具,然后转换到Elements选项卡。
它看起来应该是这样:
你可以看到DOM,点击元素,还能看见它们的细节等。
要注意在开发者工具中的DOM结构是被简化了的。文本节点只会被当作文本来显示。且并没有空白(仅有空格)的文本节点。那也没关系,因为大部分时间我们只对元素节点感兴趣。
使用鼠标(或其它指针设备)点击左上角的按钮就能在网页中选择一个节点并“检查”(在Elements选项卡中滑到此处)。这在当我们拥有一个巨大的HTML页面(相对应着一个巨大的DOM)并且想要查看某个特定的元素位置时极其有效。
另一个方法是右击页面,在菜单中选择“检查”选项。
工具栏的右方有下列子标签:
- 样式(Styles) - 我们可以看到CSS近规则应用于当前的元素规则,包括内置规则(灰色)。几乎所有的规则都能被原地编辑,包括尺寸/边距(margin)/内距(padding)。
- Computed - 查看按照属性应用于元素的CSS:我们可以看到每个属性被赋予的规则(包括CSS继承等)。
- 事件监听(Event Listeners) - 查看附加到DOM元素上的事件监听器(我们将在本教程的下一部分中介绍它们)。
- 等等
最好的学习方法是多点击几下。大多数的值都是可在原处编辑的。
与控制台的互动
当我们处理DOM时,我们可能 还想要在上面运行JavaScript。例如:运行一些代码去修改一个节点并查看结果。这里有一些在Elements选项卡和控制台之间互动的技巧。
首先:
- 在Elements选项卡中选择第一个
<li>
- 按
ESC
- 它会在Elements选项卡的下方打开控制台。
现在,最后一个被选择的元素记为$0
,其前面一个记为$1
,以此类推。
我们可以对它们运行一些命令。例如:$0.style.background = 'red'
可以使选中的列表选项变为红色,就像这样:
这就是从Console中的Elements中获取节点的方法。
除此之外,如果存在引用DOM节点的变量,那么我们就可以在控制台中使用inspect(node)
命令去在Elements窗格中查看它。
或者我们可以仅在控制台输出DOM节点并在在原地浏览,就像下面的document.body
:
当然这都是出于调试的目的。从下一章开始,我们将使用JavaScript访问和修改。
浏览器的开发者工具在开发中提供了非常大的帮助:我们可以探索DOM,尝试修改并找出问题所在。
总结
HTML/XML文档在浏览器中以DOM树的形式存在。
- 标签成为元素节点并形成结构。
- 文本变成文本节点。
- ...等等,HTML中的所有东西都在DOM中有所对应,包括注释。
我们可以使用开发者工具检测DOM并手动对其进行修改。
我们在这里只说明了基本的、最常用的和重要的一些操作。想要了解更多关于谷歌浏览器的开发者工具(Chrome Developer Tools),可以阅读https://developers.google.com/web/tools/chrome-devtools。学习这些工具的最好方法时多多点击并阅读菜单:大部分的选项都是显而易见的。当你对他们大致都熟悉的时候,再去阅读剩下的文档。
DOM节点拥有允许我们移动、修改和在页面中移动的属性和方法。我们将会在下一章节中介绍。