HTML DOM
磁盘上的 HTML 文件只保存字符。浏览器据此造出一棵活的树,这棵树就是 DOM。站牌玻璃上有两行:标题 Market,备注 Stand clear。页面已经打开时,document 就在。new document() 会抛错,new Document() 则是一份空文档,不是这块站牌。
这是一棵树,不是取整
Math 那一页是向一个共用对象要数字。这里既不取整宽度,也不用 new Date 造一个时刻。从 document 往下走:html 元素,然后 head 挨着 body,然后标题挨着备注。用多种办法选取元素、改标记、新建节点,都在后面的页面。这一页只认树的形状,并读两个节点。
每一块在站牌上的位置
每一行都是你能指到的一处。最后一列是容易走错的地方。
📊 这块站牌上的位置
| 位置 | 手里拿着什么 | 在这块站牌上 | 容易搞混 |
|---|---|---|---|
document |
树本身 | 入口,没有标签名 | 把它当成 body |
document.documentElement |
html 元素 | 标签 HTML |
把它叫成标题 |
document.head |
head 元素 | body 的兄弟 | 在这里找 Market |
document.body |
body 元素 | 标题的父元素 | 一个文本节点 |
h1#stop |
标题元素 | 文本 Market |
磁盘上保存的文件 |
| 标题里的文字 | 只有字符 | 词 Market | 一个带 id 的元素 |
标题和备注都是 body 的元素子节点,所以它们是兄弟。词 Market 不是备注的兄弟。它是标题里面的文本。tagName 返回大写,所以 html 元素报 HTML。document 这个节点没有标签,也没有父元素。
树顶上的三个名字
这三个属性点名最外层的元素。玻璃上的标题不在这三个里面。
console.log(document.documentElement.tagName);
console.log(document.head.tagName);
console.log(document.body.tagName);
三行分别是 HTML、HEAD、BODY。head 和 body 都是 html 元素的子节点,所以互为兄弟。Market 不在 head 里。head 里的页签标题是另一串文字,不是玻璃上的标题。
标题这一家
id stop 是标题元素的把手。它的父元素是 body。下一个元素兄弟是备注。
let stop = document.getElementById("stop");
console.log(stop.parentElement.tagName);
console.log(stop.nextElementSibling.id);
第一行是 BODY。第二行是 note。nextElementSibling 会跳过换行,落在段落上。上一个元素兄弟是 null,因为 body 里标题前面没有别的元素。
文字和把手是两回事
读元素,和读里面的字符,不是同一次读取。
let stop = document.getElementById("stop");
console.log(stop.textContent);
console.log(stop.id);
第一行是 Market。第二行是 stop。textContent 是字符。id 是把手。备注写的是 Stand clear,这串文字不在标题上。
先数元素,再数所有节点
children 只数元素子节点。childNodes 把文本节点也数进去,包括站牌文件里的换行。这段代码要在只含标题和备注的 body 上跑,不要在本课页面上跑,也不要在下面那份读出文件上跑。
console.log(document.body.children.length);
console.log(document.body.childNodes.length);
标题前有一次换行,两个元素之间有一次,备注后再有一次,那么 children.length 是 2,childNodes.length 是 5。多出来的三个节点是文本,里面只有空白。把两个标签贴到同一行,这些文本节点就没了,两个长度会重合。
站牌上没有的名字
去要一个文件里从没写过的 id。
console.log(document.getElementById("platform"));
console.log(document.getElementById("stop") === null);
第一行是 null。第二行是 false,因为 stop 确实在。null 的意思是没有这个元素,不是一个空标题。给 textContent 赋一段新字符串,改的是浏览器里的活树。磁盘上的 HTML 文件仍然写着 Market。
页面上的一行
第三个段落写出父元素的标签名和标题文字。脚本放在 body 末尾,等这些元素已经在树上。
<!DOCTYPE html>
<html>
<head>
<title>dom — page</title>
</head>
<body>
<h1 id="stop">Market</h1>
<p id="note">Stand clear</p>
<p id="board">…</p>
<script>
let stop = document.getElementById("stop");
let board = document.getElementById("board");
board.textContent = stop.parentElement.tagName + " / " + stop.textContent;
</script>
</body>
</html>
段落显示 BODY / Market。这份文件在脚本之前,body 里有三个元素,所以长度 2 不属于它。script 元素本身也是一个子节点。下一页会用不止一种办法选取元素。
自己把站牌走一遍
- 打出三个外层标签名,期望先是 HTML,然后 HEAD,然后 BODY
- 打出标题的父标签,期望 BODY
- 打出下一个元素兄弟的 id,期望 note
- 打出标题文字,期望 Market,再打出 id,期望 stop
- 在只有两个元素的站牌上,期望 children 的长度是 2,childNodes 的长度是 5
- 打出缺失的 id,期望 null,再和 stop 比较,期望 false
- 读段落,期望 BODY / Market
地方指错了
页面照样打开。你点到的地方不是标题所在。
- 调用
new document(),或把new Document()当成这块站牌 - 到
document.head里找 Market - 把词 Market 当成备注的元素兄弟
- 想数上换行在内的每个节点时,却去读
children.length - 只想要标题和备注时,却去读
childNodes.length - 把缺失 id 得到的
null当成空字符串 - 以为写入
textContent也会改掉磁盘上的文件
把这些分开
document是树;documentElement是 html 元素head和body是这个 html 元素下面的兄弟- 标题的父元素是 body;下一个元素兄弟是备注
textContent是字符;id是把手children只有元素;childNodes包含空白文本- 缺失的 id 是
null;保存的文件不是那棵活树 - 下一页选取元素时,不只有一种 id
🧠 测试您的知识
测试您的知识
通过这个互动测验挑战自己,看看你对这个主题的理解程度如何
📝 说明
- 仔细阅读每个问题
- 为每个问题选择最佳答案
- 您可以随时重新参加测验
- 您的进度将显示在顶部