DOM 文档对象模型
核心基础 JavaScript DOM一、向网页添加 JavaScript
1.1 三种方式(类比 CSS 的三种方式)
| 方式 | 语法 | 推荐度 |
|---|---|---|
| Inline | <body onload="alert('Hello')"> | ❌ 避免 |
| Internal | <script>alert("Hello")</script> | ⚠️ 少量使用 |
| External | <script src="index.js"></script> | ✅ 推荐 |
1.2 script 标签的位置
关键规则
始终将 <script> 放在 </body> 之前,而非 <head> 中。
html
<body>
<h1>Hello</h1>
<!-- 所有内容之后 -->
<script src="index.js"></script>
</body>原因:
- DOM 依赖:如果脚本试图操作尚未加载的元素,会报
Cannot set property of null错误 - 性能:JS 较耗时,放在底部可让页面内容先渲染,用户感知加载更快
1.3 引号嵌套
当 inline JS 中需要字符串时,外层用双引号,内层 降级为单引号:
html
<!-- ✅ 正确 -->
<body onload="alert('Hello')">
<!-- ❌ 错误:引号冲突 -->
<body onload="alert("Hello")">二、什么是 DOM
2.1 概念
DOM(Document Object Model) 是浏览器将 HTML 文档转换为的 树形对象结构。它使 JavaScript 能够动态地 选择 和 操作 页面元素。
document
└── html
├── head
│ └── title
└── body
├── h1
├── input
├── button
├── ul
│ ├── li
│ │ └── a
│ ├── li
│ └── li
└── script2.2 为什么需要 DOM
- 静态页面:HTML + CSS 写好后就固定了
- 动态交互:用户点击按钮 → 需要实时改变内容/样式
- DOM 的作用:将每个 HTML 元素变成可被 JS 选择和修改的 对象
2.3 DOM 导航
可以通过属性链式访问 DOM 树节点:
javascript
document.firstElementChild // <html>
document.firstElementChild.firstElementChild // <head>
document.firstElementChild.lastElementChild // <body>
document.firstElementChild.lastElementChild.firstElementChild // <body> 的第一个子元素💡 实际开发中不会用这种方式,但它展示了 DOM 是一个可遍历的 树结构。
三、选择元素
3.1 五种选择方法
| 方法 | 返回类型 | 选择依据 | 示例 |
|---|---|---|---|
getElementsByTagName() | 数组 | 标签名 | document.getElementsByTagName("li") |
getElementsByClassName() | 数组 | 类名 | document.getElementsByClassName("btn") |
getElementById() | 单个元素 | ID | document.getElementById("title") |
querySelector() | 单个元素 | CSS 选择器 | document.querySelector("#title") |
querySelectorAll() | 数组 | CSS 选择器 | document.querySelectorAll(".item") |
3.2 getElementsBy 系列
javascript
// 返回数组 → 需要用索引访问
document.getElementsByTagName("li")[2].style.color = "purple";
// 即使只有一个元素,也返回数组
document.getElementsByClassName("btn")[0]; // 第一个 .btn 元素
// 唯一返回单个元素的(因为 ID 唯一)
document.getElementById("title").innerHTML = "Good Bye";注意复数形式
getElementsByTagName— 复数,返回 数组getElementsByClassName— 复数,返回 数组getElementById— 单数,返回 单个元素(ID 唯一)
3.3 querySelector(推荐 ⭐)
querySelector 使用 CSS 选择器 语法,功能最强大:
javascript
// 按标签
document.querySelector("h1");
// 按 ID(加 #)
document.querySelector("#title");
// 按 class(加 .)
document.querySelector(".btn");
// 层级选择器(空格 = 后代)
document.querySelector("li a"); // li 内部的 a
// 组合选择器(无空格 = 同一元素)
document.querySelector("li.item"); // 同时是 li 和 .item 的元素
// 复杂组合
document.querySelector("#list .item"); // #list 内的 .itemquerySelector vs querySelectorAll:
javascript
// 只返回第一个匹配元素
document.querySelector(".item");
// 返回所有匹配元素(数组)
document.querySelectorAll(".item");💡 最佳实践:优先使用
querySelector/querySelectorAll,它们比getElementsBy更灵活、更常用。
四、操作样式(Style)
4.1 直接修改 style 属性
javascript
document.querySelector("h1").style.color = "red";
document.querySelector("h1").style.fontSize = "10rem";
document.querySelector("button").style.backgroundColor = "yellow";CSS → JS 属性名转换规则:
- 去掉连字符
- - 后续单词首字母 大写(驼峰)
- 值必须是 字符串
| CSS 属性 | JS 属性 |
|---|---|
font-size | fontSize |
background-color | backgroundColor |
border-radius | borderRadius |
line-height | lineHeight |
javascript
// ✅ 值必须是字符串
element.style.padding = "7%"; // 不是 7%
element.style.lineHeight = "2"; // 不是 2
element.style.visibility = "hidden";参考文档
完整的 JS Style 属性名列表可参考 DOM Style Object Properties。
五、关注点分离(Separation of Concerns)
5.1 原则
| 技术 | 职责 |
|---|---|
| HTML | 内容(Content) |
| CSS | 样式(Style) |
| JavaScript | 行为(Behavior) |
直接用 JS 修改 .style 属性 违反了 关注点分离——样式逻辑混入了行为代码。
5.2 更好的方式:classList
在 CSS 中定义样式类,用 JS 切换类名:
css
/* styles.css */
.huge {
font-size: 10rem;
color: red;
font-weight: bold;
}
.invisible {
visibility: hidden;
}javascript
// 添加类
document.querySelector("h1").classList.add("huge");
// 移除类
document.querySelector("button").classList.remove("invisible");
// 切换类(有则移除,无则添加)
document.querySelector("button").classList.toggle("invisible");classList 的三个方法:
| 方法 | 功能 | 示例 |
|---|---|---|
.add("class") | 添加类 | el.classList.add("active") |
.remove("class") | 移除类 | el.classList.remove("active") |
.toggle("class") | 切换类 | el.classList.toggle("active") |
最佳实践
样式定义在 CSS 中,JS 只负责 添加/移除类名。这样:
- 样式问题 → 查 CSS
- 行为问题 → 查 JS
- 调试效率大幅提升
六、操作文本(Text / HTML)
6.1 innerHTML vs textContent
javascript
// 假设 HTML: <h1><strong>Hello</strong></h1>
document.querySelector("h1").innerHTML;
// "<strong>Hello</strong>" ← 包含 HTML 标签
document.querySelector("h1").textContent;
// "Hello" ← 纯文本,无标签区别:
| 属性 | 返回内容 | 可设置 HTML? |
|---|---|---|
innerHTML | 标签内的 完整 HTML | ✅ 可以 |
textContent | 标签内的 纯文本 | ❌ 不行 |
javascript
// 可以通过 innerHTML 注入 HTML
document.querySelector("h1").innerHTML = "<em>Good Bye</em>";
// 结果:h1 中显示斜体的 "Good Bye"
// textContent 会原样显示
document.querySelector("h1").textContent = "<em>Good Bye</em>";
// 结果:h1 中显示文本 "<em>Good Bye</em>"七、操作属性(Attributes)
7.1 查看、获取、设置
javascript
var link = document.querySelector("a");
// 查看所有属性
link.attributes; // NamedNodeMap {0: href, ...}
// 获取某个属性的值
link.getAttribute("href"); // "https://www.google.com"
// 设置属性值
link.setAttribute("href", "https://www.bing.com");属性 = HTML 标签内除标签名外的所有键值对:
html
<a href="..." class="link" id="main-link">
<!-- ^^^^ ^^^^^ ^^ 这些都是属性 -->八、对象的属性与方法
DOM 中的每个元素都是一个 对象,拥有 属性(Properties) 和 方法(Methods):
8.1 类比:汽车对象
javascript
// 属性 — 描述对象的特征
car.color; // "red" (getter)
car.numberOfDoors = 0; // 设置为 0 (setter)
// 方法 — 对象能做的事(本质是函数)
car.drive();
car.brake();
car.park();8.2 DOM 对象示例
javascript
var btn = document.querySelector("button");
// 属性(无括号)
btn.innerHTML; // 按钮内的 HTML
btn.style.color; // 文字颜色
btn.firstChild; // 第一个子节点
// 方法(有括号)
btn.click(); // 模拟点击
btn.appendChild(el); // 添加子元素
btn.setAttribute("class", "new"); // 修改属性属性 vs 方法的识别
- 属性:用
.访问,无括号 →btn.innerHTML - 方法:用
.调用,有括号 →btn.click()
方法本质上就是 关联到对象的函数。