上一节我们学习了JS中DOM的一些基础操作,本节我们开始学习DOM的遍历。我们都知道,DOM的本质其实是一棵树,因此,当我们获取某个元素时,我们可以根据DOM方法来获取该元素上一级的所有节点或下一级的所有节点,就像是树的遍历一样,通过一个元素拿到相关元素。下面我们通过表格展示一些DOM树遍历的内置属性和方法:
| 函数/属性 | 功能 |
|---|---|
| parentNode | 返回当前节点的父节点 |
| parentElement | 返回当前节点的父元素节点 |
| childNodes | 返回当前节点的所有子节点的集合 |
| children | 返回当前节点的所有元素子节点的集合 |
| firstChild | 返回当前节点的第一个子节点 |
| firstElementChild | 返回当前节点的第一个元素子节点 |
| lastChild | 返回当前节点的最后一个子节点 |
| lastElementChild | 返回当前节点的最后一个元素子节点 |
| nextSibling | 返回当前节点的下一个兄弟节点 |
| nextElementSibling | 返回当前节点的下一个元素兄弟节点 |
| previousSibling | 返回当前节点的上一个兄弟节点 |
| previousElementSibling | 返回当前节点的上一个元素兄弟节点 |
| querySelector() | 返回文档中匹配指定CSS选择器的第一个元素 |
| querySelectorAll() | 返回文档中匹配指定CSS选择器的所有元素 |
| getElementById() | 返回对拥有指定id的第一个对象的引用 |
| getElementsByClassName() | 返回文档中所有指定类名的元素集合 |
| getElementsByTagName() | 返回带有指定标签名的对象集合 |
| closest() | 返回当前元素中与选择器匹配的最接近的祖先元素 |
比如我们现在有一个简单的页面,包括header、main和footer:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dotcpp编程</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: sans-serif;
line-height: 1.6;
}
.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
padding: 1rem 0;
}
/* 导航栏样式 */
header {
border-bottom: 1px solid #ccc;
padding: 1rem 0;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.2rem;
font-weight: bold;
}
.nav-links {
display: flex;
list-style: none;
}
.nav-links li {
margin-left: 1.5rem;
}
.nav-links a {
text-decoration: none;
color: #333;
}
/* 主要内容区域样式 */
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
margin-top: 1.5rem;
}
.card {
border: 1px solid #ccc;
padding: 1rem;
}
.card h3 {
margin-bottom: 0.5rem;
}
/* 页脚样式 */
footer {
border-top: 1px solid #ccc;
padding: 1rem 0;
margin-top: 2rem;
}
.footer-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.footer-links {
display: flex;
list-style: none;
}
.footer-links li {
margin-left: 1rem;
}
.footer-links a {
text-decoration: none;
color: #333;
}
</style>
</head>
<body>
<!-- 导航栏 -->
<header>
<div class="container">
<nav>
<div class="logo">Dotcpp编程</div>
<ul class="nav-links">
<li><a href="#">首页</a></li>
<li><a href="#">服务</a></li>
<li><a href="#">产品</a></li>
<li><a href="#">关于我们</a></li>
<li><a href="#">联系我们</a></li>
</ul>
</nav>
</div>
</header>
<!-- 主要内容区域 -->
<main>
<div class="container">
<h1>DOM遍历</h1>
<div class="grid-container">
<div class="card">
<h3>服务一</h3>
<p>这里是服务一的简要描述。</p>
</div>
<div class="card">
<h3>服务二</h3>
<p>这里是服务二的简要描述。</p>
</div>
<div class="card">
<h3>服务三</h3>
<p>这里是服务三的简要描述。</p>
</div>
<div class="card">
<h3>服务四</h3>
<p>这里是服务四的简要描述。</p>
</div>
<div class="card">
<h3>服务五</h3>
<p>这里是服务五的简要描述。</p>
</div>
<div class="card">
<h3>服务六</h3>
<p>这里是服务六的简要描述。</p>
</div>
</div>
</div>
</main>
<!-- 页脚 -->
<footer>
<div class="container">
<div class="footer-content">
<div class="copyright">
© 2025@Dotcpp编程
</div>
<ul class="footer-links">
<li><a href="#">隐私政策</a></li>
<li><a href="#">使用条款</a></li>
<li><a href="#">网站地图</a></li>
</ul>
</div>
</div>
</footer>
<script></script>
</body>
</html>该页面的结构如下:
html ├── head │ ├── meta │ ├── meta │ ├── title │ └── style └── body ├── header │ └── div │ └── nav │ ├── div │ └── ul │ ├── li │ │ └── a │ ├── li │ │ └── a │ ├── li │ │ └── a │ ├── li │ │ └── a │ └── li │ └── a ├── main │ └── div │ ├── h1 │ └── div │ ├── div │ │ ├── h3 │ │ └── p │ ├── div │ │ ├── h3 │ │ └── p │ ├── div │ │ ├── h3 │ │ └── p │ ├── div │ │ ├── h3 │ │ └── p │ ├── div │ │ ├── h3 │ │ └── p │ └── div │ ├── h3 │ └── p ├── footer │ └── div │ └── div │ ├── div │ └── ul │ ├── li │ │ └── a │ ├── li │ │ └── a │ └── li │ └── a └── script
具体遍历操作:
关于父子节点和父子元素之间的区别:节点包含的范围更大,注释、文本或者是空行、缩进都算是一个节点;而元素值得是HTML里内置的默认元素或是自定义元素。
1. 父子节点相互访问:对于body,文本节点(header前的换行和缩进)、<!-- 导航栏 -->···文本节点 (body结束前的换行和缩进)、<script>是它的子节点,它们可以相互访问:
/*父子节点相互访问*/
const father = document.querySelector('body')//取body标签
const son1=document.querySelector('header')//取header
const son2=document.querySelector('main')//取main
const son3=document.querySelector('footer')//取footer
/* 向下访问*/
const arrF=father.childNodes
console.log(arrF[0]);// 文本节点 (header前的换行和缩进)
console.log(arrF[1]);// 注释节点 <!-- 导航栏 -->
console.log(arrF[2]);// 文本节点 (header后的换行和缩进)
console.log(arrF[3]);// header元素
console.log(arrF[4]);// 文本节点 (main前的换行和缩进)
console.log(arrF[5]);// 注释节点 <!-- 主要内容区域 -->
console.log(arrF[6]);// 文本节点 (main后的换行和缩进)
console.log(arrF[7]);// main元素
console.log(arrF[8]);// 文本节点 (footer前的换行和缩进)
console.log(arrF[9]);// 注释节点 <!-- 页脚 -->
console.log(arrF[10]);// 文本节点 (footer后的换行和缩进)
console.log(arrF[11]);// footer元素
console.log(arrF[12]);// 文本节点 (body结束前的换行和缩进)
/* 向上访问(由于非元素节点不好获取,这里就不具体展示了) */
console.log(son1.parentNode);//body
console.log(son2.parentNode);//body
console.log(son3.parentNode);//body2.父子元素相互访问:同节点访问方式一样,只不过元素的话相比节点约束性大。对于body,它的子元素是header、main和footer。它们也可以相互访问:
/* 父子元素相互访问 */
const father = document.querySelector('body')//取body标签
const son1=document.querySelector('header')//取header
const son2=document.querySelector('main')//取main
const son3=document.querySelector('footer')//取footer
/* 向下访问*/
const arrF=father.children
console.log(arrF.length);
console.log(arrF[0]);// header元素
console.log(arrF[1]);// main元素
console.log(arrF[2]);// footer元素
console.log(arrF[3]);// <scripe>
/* 向上访问 */
console.log(son1.parentNode);//body
console.log(son2.parentNode);//body
console.log(son3.parentNode);//body3. 首尾节点、元素的访问:需要注意的是,该获取方式针对的是获取元素的下一级的范围,并非同级。比如body的下一级,然后由该元素进行首尾节点、元素的访问:
/* 首尾元素、节点访问 */
const father = document.querySelector('body')//取body标签
console.log(father.firstElementChild);//首元素-header
console.log(father.firstChild);//首节点-文本节点 (header前的换行和缩进)
console.log(father.lastElementChild);//尾元素-<script>
console.log(father.lastChild);//尾节点-<script>4. 兄弟节点元素的访问:同级元素,而非下一级元素。比如我们可以通过main来获取前后元素和节点:
/*兄弟元素前后节点、元素访问*/
const son2 = document.querySelector('main') // 取main
console.log(son2.previousSibling); // 前一个兄弟节点 (文本节点)
console.log(son2.nextSibling); // 后一个兄弟节点 (文本节点)
console.log(son2.previousElementSibling); // 前一个兄弟元素 (header)
console.log(son2.nextElementSibling); // 后一个兄弟元素 (footer)总结:通过DOM树的遍历,我们可以灵活地获取元素,进而调整页面布局和内容。
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程