JavaScript DOM 導航

在本教程中,你將學習如何在 JavaScript 中的 DOM 節點之間導航。

在 DOM 節點之間導航

在前面的章節中,你已經學習瞭如何在網頁上選擇單個元素。但是在很多情況下,你需要訪問子元素、父元素或祖先元素。請參閱 JavaScript DOM 節點 一章,瞭解 DOM 樹中節點之間的邏輯關係。

DOM 節點提供了幾個屬性和方法,允許你導航或遍歷 DOM 的樹結構並輕鬆進行更改。在下一節中,我們將學習如何使用 JavaScript 在 DOM 樹中向上,向下和橫向導航。

訪問子節點

你可以使用 DOM 節點的 firstChildlastChild 屬性分別訪問節點的第一個和最後一個直接子節點。如果節點沒有任何子元素,則返回 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 節點。

要避免 firstChildlastChild 返回 #text#comment 節點的問題,你可以使用 firstElementChildlastElementChild 屬性分別僅返回第一個和最後一個元素節點。但是,它不適用於 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>

訪問兄弟節點

你可以使用 previousSiblingnextSibling 屬性分別訪問 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>

或者,你可以使用 previousElementSiblingnextElementSibling 來獲取前一個和下一個兄弟元素,跳過任何空白文字節點。如果沒有這樣的兄弟節點,所有這些屬性都會返回 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 文件。