DOM 节点概述
当网页在浏览器中加载时,会创建一个文档对象。'document' 对象是网页的根节点,你可以通过它访问网页中的其他 HTML 节点。
在 HTML DOM 中,一切都是节点:
你可以访问所有的 HTML DOM 节点。
HTML DOM 节点之间的关系
在 HTML DOM 中,每个节点与其他节点之间存在关系。每个节点都在 DOM 树中的层次结构里。
以下是本章中将使用的术语:
-
-
父节点 - 每个节点都有一个父节点,根节点没有父节点。
-
-
兄弟节点 - 同一层级上的节点,具有相同的父节点。
让我们通过下面的例子来理解节点之间的关系:
<html>
<head>
<title> JavaScrip - DOM Navigation </title>
</head>
<body>
<div>
<h3> Hi Users! </h3>
<p> Hello World! </p>
</div>
</body>
</html>
在上述示例中,
-
-
<html>
节点包含两个子元素:<body>
和 <head>
。
-
<head>
元素包含单一子元素:<title>
。
-
-
-
<div>
节点包含两个子节点:<h3>
和 <p>
。
-
-
<h3>
和 <p>
的父节点是 <div>
节点。
-
使用 JavaScript 导航 DOM 节点
在 DOM 树中导航节点意味着找到特定元素的父节点、子节点、兄弟节点等。
你可以使用以下方法和属性来在 DOM 树中导航:
属性 |
描述 |
firstChild |
获取特定节点的第一个子节点,也可以返回文本、注释等。 |
firstElementChild |
获取第一个子元素,例如 <p> , <div> , <img> 等。 |
lastChild |
获取特定节点的最后一个子节点,也可以返回文本、注释等。 |
lastElementChild |
获取最后一个子元素。 |
childNodes |
获取特定元素所有子节点的列表。 |
children |
获取特定元素所有子元素的 HTML 集合。 |
parentNode |
获取 HTML 元素的父节点。 |
parentElement |
获取 HTML 元素的父元素节点。 |
nextSibling |
获取同一层级具有相同父节点的下一个节点。 |
nextElementSibling |
获取同一层级具有相同父节点的下一个元素节点。 |
previousSibling |
获取同一层级具有相同父节点的前一个节点。 |
previousElementSibling |
获取同一层级具有相同父节点的前一个元素节点。 |
下面我们将使用每个方法来遍历 DOM 元素。
访问第一个子元素
你可以使用 firstChild
或 firstElementChild
属性来访问特定子元素。
语法
使用 firstChild
和 firstElementChild
属性来访问第一个子元素的语法如下:
element.firstChild;
element.firstElementChild;
示例
在下面的代码中,<div>
元素包含一些文本,后面跟着三个 <p>
元素。
当我们使用 firstChild
属性时,它返回包含 'Numbers' 文本的文本节点;当我们使用 firstElementChild
属性时,它返回第一个 <p>
元素。
<!DOCTYPE html>
<html>
<body>
<div id="num">Numbers
<p> One </p>
<p> Two </p>
<p> Three </p>
</div>
<div id="demo"></div>
<script>
const output = document.getElementById('demo');
const numbers = document.getElementById('num');
output.innerHTML += "numbers.firstChild: " + numbers.firstChild.textContent.trim() + "<br>";
output.innerHTML += "numbers.firstElementChild: " + numbers.firstElementChild.textContent + "<br>";
</script>
</body>
</html>
访问最后一个子元素
你可以使用 lastChild
或 lastElementChild
属性来访问特定 HTML 节点的最后一个子元素。
语法
使用 lastChild
和 lastElementChild
属性来访问最后一个子元素的语法如下:
element.lastChild;
element.lastElementChild;
示例
在下面的代码中,我们定义了一个包含 3 个 <p>
元素的 <div>
元素,这些元素包含编程语言的名字。
在输出中,你可以看到 lastElementChild
属性返回最后一个 <p>
元素,而 lastChild
属性则返回 <div>
元素的文本节点。
<!DOCTYPE html>
<html>
<body>
<div id="lang">
<p> Java </p>
<p> JavaScript </p>
<p> HTML </p>
Programming Languages
</div>
<div id="demo"></div>
<script>
const output = document.getElementById('demo');
const langs = document.getElementById('lang');
output.innerHTML += "langs.lastChild: " + langs.lastChild.textContent.trim() + "<br>";
output.innerHTML += "langs.lastElementChild: " + langs.lastElementChild.textContent + "<br>";
</script>
</body>
</html>
访问 HTML 元素的所有子元素
你可以使用 childNodes
属性来访问所有子节点的列表,或者使用 children
属性来访问所有子元素的 HTML 集合。
语法
使用 children
和 childNodes
属性来访问所有子元素的语法如下:
element.children;
element.childNodes;
示例
在下面的代码中,我们使用 childNodes
属性来访问 <div>
元素的所有子节点。
在输出中,你会看到它也返回了带有未定义文本的文本节点,因为它包含每个 HTML 元素节点前后出现的文本节点。
<!DOCTYPE html>
<html>
<body>
<div id="lang">
<p> Java </p>
<p> JavaScript </p>
<p> HTML </p>
programming Languages
</div>
<div id="output"></div>
<script>
let output = document.getElementById('output');
let langs = document.getElementById('lang');
output.innerHTML += "All children of the div element are - " + "<br>";
let allChild = langs.childNodes;
for (let i = 0; i < allChild.length; i++) {
output.innerHTML += allChild[i].nodeName + " " + allChild[i].innerHTML + "<br>";
}
</script>
</body>
</html>
访问 HTML 元素的父节点
你可以使用 parentNode
属性来访问特定 HTML 节点的父节点。
语法
使用 parentNode
属性的语法如下:
element.parentNode;
示例
在下面的代码中,我们访问 JavaScript 中 id 为 'blue' 的 <li>
元素。然后我们使用 parentNode
属性来访问父节点。
它返回的是 'UL' 节点,这可以在输出中观察到。
<!DOCTYPE html>
<html>
<body>
<ul id="color">
<li id="blue"> Blue </li>
<li> Pink </li>
<li> Red </li>
</ul>
<div id="output">The child node of the color list is: </div>
<script>
const blue = document.getElementById('blue');
document.getElementById('output').innerHTML += blue.parentNode.nodeName;
</script>
</body>
</html>
访问下一个兄弟节点
nextSibling
属性用于访问下一个兄弟节点。
语法
使用 nextSibling
属性的语法如下:
element.nextSibling;
示例
在下面的代码中,我们访问了 id 为 'apple' 的 <li>
元素,并使用 nextSibling
属性访问下一个兄弟节点。它返回 id 为 'banana' 的 <li>
节点。
<!DOCTYPE html>
<html>
<body>
<ul id="fruit">
<li id="apple"> Apple </li>
<li id="banana"> Banana </li>
<li id="watermelon"> Watermelon </li>
</ul>
<div id="output">The next sibling node of the apple node is: </div>
<script>
const apple = document.getElementById('apple');
document.getElementById('output').innerHTML += apple.nextElementSibling.textContent;
</script>
</body>
</html>
访问前一个兄弟节点
previousSibling
属性用于从 DOM 树中访问前一个兄弟节点。
语法
使用 previousSibling
属性的语法如下:
element.previousSibling;
示例
在下面的代码中,我们访问了 id 为 'banana' 的 <li>
元素的前一个兄弟节点。它返回 id 为 'apple' 的 <li>
元素。
<!DOCTYPE html>
<html>
<body>
<ul id="fruit">
<li id="apple"> Apple </li>
<li id="banana"> Banana </li>
<li id="watermelon"> Watermelon </li>
</ul>
<div id="output">The previous sibling node of the banana node is: </div>
<script>
const banana = document.getElementById('banana');
document.getElementById('output').innerHTML += banana.previousElementSibling.textContent;
</script>
</body>
</html>
DOM 根节点
在 HTML DOM 中包含有两个根节点:
-
document.body
- 返回文档的 <body>
元素。
-
document.documentElement
- 返回整个 HTML 文档。
示例:使用 document.body
<!DOCTYPE html>
<html>
<body>
<div> This is demo! </div>
<div id="output"> </div>
<script>
const output = document.getElementById('output');
output.innerHTML += "The body of the document is: " + document.body.innerHTML;
</script>
</body>
</html>
示例:使用 document.documentElement
<!DOCTYPE html>
<html>
<body>
<h1> Hi, Users! </h1>
<div id="output"> </div>
<script>
const output = document.getElementById('output');
output.innerHTML += "The full document is " + document.documentElement.innerHTML;
</script>
</body>
</html>
DOM nodeName 属性
HTML DOM 元素的 nodeName
属性用于获取节点的名称,并且有如下的规定:
语法
使用 nodeName
属性获取节点名称的语法如下:
element.nodeName;
示例
在下面的代码中,我们访问了 <div>
元素并且使用了 nodeName
属性。它返回了大写的标签名。
<!DOCTYPE html>
<html>
<body>
<div id = "output"> </div>
<script>
const output = document.getElementById('output');
output.innerHTML = "The node name of the div node is: " + output.nodeName;
</script>
</body>
</html>
DOM nodeValue 属性
nodeValue
用于获取节点的值,并且有如下的规定:
-
-
文本节点的
nodeValue
是节点内的文本本身。
-
语法
使用 nodeValue
属性获取节点值的语法如下:
element.nodeValue;
示例
在下面的代码中,<div>
元素包含了一些文本以及 <p>
元素。
<div>
元素的第一个子元素是文本节点,<div>
元素的第二个子节点是 <p>
元素。
在输出中,你可以看到当你使用 nodeValue
属性与文本节点一起使用时,它返回文本。否则,当你与 HTML 元素节点一起使用时,它返回 null
。
<!DOCTYPE html>
<html>
<body>
<div id = "num">
Numbers
<p> One </p>
</div>
<div id = "output"> </div>
<script>
const output = document.getElementById('output');
const num = document.getElementById('num');
let child = num.childNodes;
output.innerHTML += "The value of the first child is: " + child[0].nodeValue + "<br>";
output.innerHTML += "The value of the second child is: " + child[1].nodeValue + "<br>";
</script>
</body>
</html>
DOM 中的节点类型
下面列出了 HTML DOM 中的不同类型的节点:
节点类型 |
类型编号 |
描述 |
元素节点 |
1 |
元素节点可以有子节点、属性和文本内容。例如,<div> , <a> 等都是元素节点。 |
文本节点 |
3 |
文本节点可以包含节点内的文本内容。例如,在 <p> , <div> 等元素内的文本。 |
注释节点 |
8 |
注释节点包含注释。 |
文档节点 |
9 |
表示整个文档。 |
文档类型节点 |
10 |
表示文档的类型。例如,<!Doctype html> |
DOM nodeType 属性
nodeType
属性返回节点的类型,如上表所示。
语法
使用 nodeType
属性获取节点类型的语法如下:
element.nodeType;
示例
在下面的代码中,我们使用 nodeType
属性获取节点的类型。
<!DOCTYPE html>
<html>
<body>
<div id = "output"> </div>
<script>
const output = document.getElementById('output');
output.innerHTML += "The type of the div node is: " + output.nodeType;
</script>
</body>
</html>