JavaScript DOM 导航
在本教程中,你将学习如何在 JavaScript 中的 DOM 节点之间导航。
在 DOM 节点之间导航
在前面的章节中,你已经学习了如何在网页上选择单个元素。但是在很多情况下,你需要访问子元素、父元素或祖先元素。请参阅 JavaScript DOM 节点 一章,了解 DOM 树中节点之间的逻辑关系。
DOM 节点提供了几个属性和方法,允许你导航或遍历 DOM 的树结构并轻松进行更改。在下一节中,我们将学习如何使用 JavaScript 在 DOM 树中向上,向下和横向导航。
访问子节点
你可以使用 DOM 节点的 firstChild
和 lastChild
属性分别访问节点的第一个和最后一个直接子节点。如果节点没有任何子元素,则返回 null
。
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
console.log(main.firstChild.nodeName); // Prints: #text
var hint = document.getElementById("hint");
console.log(hint.firstChild.nodeName); // Prints: SPAN
</script>
注意: nodeName
是一个只读属性,它将当前节点的名称作为字符串返回。例如,它返回元素节点, #text
文本节点, #comment
注释节点, #document
文档节点等的标记名称。
如果你注意到上面的示例,则主 DIV 元素的第一个子节点的 nodeName
返回 #text
而不是 H1
。因为空格、制表符、换行符等空格是有效字符,它们形成 #text
节点并成为 DOM 树的一部分。因此,由于 <div>
标记在 <h1>
标记之前包含换行符,因此它将创建一个 #text
节点。
要避免 firstChild
和 lastChild
返回 #text
或 #comment
节点的问题,你可以使用 firstElementChild
和 lastElementChild
属性分别仅返回第一个和最后一个元素节点。但是,它不适用于 IE 9 及更早版本。
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
alert(main.firstElementChild.nodeName); // Outputs: H1
main.firstElementChild.style.color = "red";
var hint = document.getElementById("hint");
alert(hint.firstElementChild.nodeName); // Outputs: SPAN
hint.firstElementChild.style.color = "blue";
</script>
类似地,你可以使用 childNodes
属性访问给定元素的所有子节点,其中第一个子节点被指定为索引 0
.这是一个示例:
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
// First check that the element has child nodes
if(main.hasChildNodes()) {
var nodes = main.childNodes;
// Loop through node list and display node name
for(var i = 0; i < nodes.length; i++) {
alert(nodes[i].nodeName);
}
}
</script>
childNodes
返回所有子节点,包括像文字和注释节点非元素节点。要仅获取元素的集合,请改用 children
属性。
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
// First check that the element has child nodes
if(main.hasChildNodes()) {
var nodes = main.children;
// Loop through node list and display node name
for(var i = 0; i < nodes.length; i++) {
alert(nodes[i].nodeName);
}
}
</script>
访问父节点
你可以使用 parentNode
属性访问 DOM 树中指定节点的父节点。
文档节点的 parentNode
将始终返回 null
,因为它没有父节点。
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var hint = document.getElementById("hint");
alert(hint.parentNode.nodeName); // Outputs: DIV
alert(document.documentElement.parentNode.nodeName); // Outputs: #document
alert(document.parentNode); // Outputs: null
</script>
提示: 最顶层的 DOM 树节点可以作为 document
属性直接访问。例如,可以使用 document.documentElement
属性访问 <html>
元素,可以使用 document.head
属性访问 <head>
元素,并且可以使用 document.body
属性访问 <body>
元素。
但是,如果你只想获取元素节点,可以使用 parentElement
,如下所示:
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var hint = document.getElementById("hint");
alert(hint.parentNode.nodeName); // Outputs: DIV
hint.parentNode.style.backgroundColor = "yellow";
</script>
访问兄弟节点
你可以使用 previousSibling
和 nextSibling
属性分别访问 DOM 树中的上一个和下一个节点。这是一个例子:
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p><hr>
</div>
<script>
var title = document.getElementById("title");
alert(title.previousSibling.nodeName); // Outputs: #text
var hint = document.getElementById("hint");
alert(hint.nextSibling.nodeName); // Outputs: HR
</script>
或者,你可以使用 previousElementSibling
和 nextElementSibling
来获取前一个和下一个兄弟元素,跳过任何空白文本节点。如果没有这样的兄弟节点,所有这些属性都会返回 null
。这是一个例子:
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var hint = document.getElementById("hint");
alert(hint.previousElementSibling.nodeName); // Outputs: H1
alert(hint.previousElementSibling.textContent); // Outputs: My Heading
var title = document.getElementById("title");
alert(title.nextElementSibling.nodeName); // Outputs: P
alert(title.nextElementSibling.textContent); // Outputs: This is some text.
</script>
textContent
属性表示节点及其所有后代的文本内容。请参阅 JavaScript DOM 操作 章节以了解有关它的更多信息。
DOM 节点的类型
DOM 树由不同类型的节点组成,例如元素、文本、注释等。
每个节点都有一个 nodeType
属性,你可以使用该属性来找出你正在处理的节点类型。下表列出了最重要的节点类型:
不变 | 值 | 描述 |
---|---|---|
ELEMENT_NODE |
1 | 一个元素节点,如 <p> 或 <img> 。 |
TEXT_NODE |
3 | 元素的实际文本。 |
COMMENT_NODE |
8 | 评论节点即 <!-- some comment --> |
DOCUMENT_NODE |
9 | 文档节点,即 <html> 元素的父节点。 |
DOCUMENT_TYPE_NODE |
10 | 文档类型节点,例如 <!DOCTYPE html> 用于 HTML5 文档。 |