跟着 MDN 学JavaScript day_26:DOM脚本编程入门完全指南
引言:文档对象模型的重要性
在Web开发的学习旅程中,当掌握了JavaScript的基本语法和对象概念之后,下一个重要的里程碑就是学会如何与网页文档进行交互。编写网页和应用程序时,开发者最核心的需求之一就是能够以编程方式操纵文档结构,动态地改变页面内容和样式,响应用户的操作。这一切的实现都依赖于文档对象模型(DOM,Document Object Model)。
DOM是一套庞大的API集合,它大量使用了Document对象,为开发者提供了控制HTML结构和样式信息的标准化接口。通过DOM,JavaScript得以将静态的HTML文档转变为一个可编程操作的对象结构,使得页面不再是固定不变的,而是可以根据用户行为、数据变化或任何其他条件动态更新。
一、Web浏览器的重要部分:理解全局上下文
Web浏览器是一个非常复杂的软件系统,由许多活动部件协同工作。出于安全考虑,浏览器对Web开发者能够控制和操纵的部分做了严格限制——这种安全沙箱机制是Web生态健康发展的重要保障。
在浏览器的架构中,有三个最核心的部分是开发者会频繁接触的:
| 对象 | JavaScript表示 | 职责 |
|---|---|---|
| 窗口 | Window |
浏览器标签页的全局对象,所有全局变量和函数都是其成员 |
| 导航器 | Navigator |
代表浏览器状态和身份(用户代理),提供语言、在线状态等信息 |
| 文档 | Document |
加载到窗口中的页面内容的DOM表示,是DOM操作的入口 |
// Window:页面运行环境
window.innerWidth; // 获取窗口宽度
window.innerHeight; // 获取窗口高度
// Navigator:浏览器信息
navigator.language; // 用户首选语言
navigator.onLine; // 浏览器是否在线
// Document:页面的 DOM 入口
document.title; // 页面标题
Window对象处于浏览器JavaScript环境的顶层,代表着整个浏览器页面的运行环境。Document是本文的重点,但理解三者的角色同样重要。
二、文档对象模型:树状结构的核心概念
每一个浏览器标签页中加载的文档,都由一个文档对象模型来表示。DOM是由浏览器创建的树状结构表示,将HTML文档的结构映射为节点树。
2.1 示例HTML文档
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<title>Simple DOM example</title>
</head>
<body>
<section>
<img
src="dinosaur.png"
alt="A red Tyrannosaurus Rex" />
<p>
Here we will add a link to the
<a href="https://www.mozilla.org/">Mozilla homepage</a>
</p>
</section>
</body>
</html>
2.2 DOM树可视化
document
└── html (根节点)
├── head
│ ├── meta
│ └── title
│ └── #text: "Simple DOM example"
└── body
└── section
├── img
└── p
├── #text: "Here we will add a link to the "
└── a (href="https://www.mozilla.org/")
└── #text: "Mozilla homepage"
2.3 节点类型与关系术语
| 术语 | 定义 | 示例 |
|---|---|---|
| 元素节点 | 代表HTML元素 | <section>、<p>、<img> |
| 文本节点 | 代表元素的文本内容 | #text |
| 根节点 | DOM树顶层节点 | <html> |
| 父节点 | 包含其他节点的节点 | <body> 是 <section> 的父节点 |
| 子节点 | 直接位于另一个节点内部的节点 | <img> 是 <section> 的子节点 |
| 后代节点 | 位于另一个节点内部任意层级的节点 | <img> 是 <body> 的后代节点 |
| 兄弟节点 | DOM树中同层级、共享同一父节点的节点 | <img> 和 <p> 是兄弟节点 |
这些术语不仅在DOM编程中频繁出现,在CSS选择器中也有对应的概念。熟悉这些术语对于理解和编写DOM操作代码至关重要。
三、基本DOM操作:从选择到修改的完整流程
操作DOM内的元素,第一步始终是选择目标元素,并将其引用存储在一个变量中。
3.1 现代选择方法
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
document.querySelector() |
CSS选择器 | 单个元素 | 返回第一个匹配的元素 |
document.querySelectorAll() |
CSS选择器 | NodeList |
返回所有匹配的元素集合 |
const link = document.querySelector("a");
// 选择文档中第一个 <a> 元素
const allLinks = document.querySelectorAll("a");
// 选择文档中所有 <a> 元素,返回 NodeList
3.2 传统选择方法
document.getElementById("header"); // 通过 id 选择
document.getElementsByTagName("div"); // 通过标签名选择
document.getElementsByClassName("box"); // 通过类名选择
querySelector()和querySelectorAll()是推荐的现代方法,灵活性远高于传统方法。
3.3 修改元素属性和内容
const link = document.querySelector("a");
link.textContent = "Mozilla Developer Network"; // 修改文本内容
link.href = "https://developer.mozilla.org"; // 修改链接目标
| 属性 | 作用 | 示例 |
|---|---|---|
textContent |
获取/设置元素的文本内容 | link.textContent = "新文字" |
href |
<a> 元素的链接地址 |
link.href = "https://..." |
src |
<img> 元素的图片地址 |
img.src = "photo.jpg" |
value |
表单元素的值 | input.value = "..." |
四、创建和放置新节点:动态构建页面内容
掌握了选择已有元素的方法之后,下一个关键技能是创建新元素并将它们添加到文档中。
4.1 创建元素
const sect = document.querySelector("section");
const para = document.createElement("p");
para.textContent = "We hope you enjoyed the ride.";
此时新元素只存在于JavaScript的内存中,并没有出现在页面上。
4.2 追加到页面
sect.appendChild(para);
Node.appendChild() 将指定节点追加到调用者的子节点列表末尾。
4.3 创建文本节点
const text = document.createTextNode(
" — the premier source for web development knowledge.",
);
const linkPara = document.querySelector("p");
linkPara.appendChild(text);
Document.createTextNode() 创建纯文本节点,适用于需要保留元素内已有内容、只追加新文本的场景。
4.4 DOM操作三步走模式
① createElement("标签名") → 在内存中创建元素
② textContent = "内容" → 设置元素文本
③ parent.appendChild(el) → 添加到页面
五、移动和删除元素:灵活控制DOM结构
5.1 移动元素
由于DOM中每个元素只能存在于一个位置,将已有元素 appendChild() 到另一个父节点时,它会自动从原位置移动到新位置。
sect.appendChild(linkPara);
// linkPara 从原来的位置移动到 sect 的底部
linkPara持有的是该元素的唯一实例引用,appendChild()操作的是同一个元素,不是复制。如需复制,使用Node.cloneNode()。
5.2 删除元素
| 方法 | 语法 | 兼容性 |
|---|---|---|
Node.removeChild() |
parent.removeChild(child) |
所有浏览器 |
Element.remove() |
element.remove() |
现代浏览器 |
| 传统兼容写法 | element.parentNode.removeChild(element) |
所有浏览器 |
// 方式一:通过父节点删除(需持有父节点引用)
sect.removeChild(linkPara);
// 方式二:元素自己移除(现代写法)
linkPara.remove();
// 方式三:传统兼容写法
linkPara.parentNode.removeChild(linkPara);
六、操作样式:JavaScript与CSS的协作之道
6.1 方式一:直接操作 style 属性(内联样式)
para.style.color = "white";
para.style.backgroundColor = "black";
para.style.padding = "10px";
para.style.width = "250px";
para.style.textAlign = "center";
CSS属性名 → JavaScript属性名转换规则:去掉连字符,将连字符后的字母大写。
| CSS属性名 | JavaScript属性名 |
|---|---|
background-color |
backgroundColor |
text-align |
textAlign |
font-size |
fontSize |
margin-top |
marginTop |
⚠️ 混淆两种命名方式是初学者常见错误。
6.2 方式二:操作 class 属性(推荐)
将样式定义保留在CSS中,JavaScript只负责切换类名,实现样式和行为分离。
/* CSS 文件 */
.highlight {
color: white;
background-color: black;
padding: 10px;
width: 250px;
text-align: center;
}
// JavaScript 文件
para.setAttribute("class", "highlight");
6.3 两种方式对比
| 维度 | element.style |
切换 class |
|---|---|---|
| 维护性 | ❌ 样式散落在JS中 | ✅ CSS集中管理 |
| 关注点分离 | ❌ 混合 | ✅ 分离 |
| 适用场景 | 运行时动态计算的值 | 预定义的样式变体 |
| 优先级 | 内联样式(最高) | 样式表中的规则 |
七、实战项目:动态购物清单应用
让我们通过构建一个动态购物清单应用来综合运用所学的DOM操作技能。
7.1 需求分析
| 功能 | 描述 |
|---|---|
| 添加项目 | 用户在输入框中输入购物项目,点击按钮后添加到清单 |
| 删除项目 | 每个清单项旁有删除按钮,点击可移除该项目 |
| 自动清空 | 添加项目后输入框自动清空并重新获得焦点 |
7.2 获取DOM引用
const list = document.querySelector("ul");
const input = document.querySelector("input");
const button = document.querySelector("button");
7.3 添加按钮的点击处理
button.addEventListener("click", () => {
const myItem = input.value; // ① 先保存输入值
input.value = ""; // ② 再清空输入框
⚠️ 顺序很重要:必须先保存值再清空,否则会丢失用户输入的内容。
7.4 创建DOM元素并组装
const listItem = document.createElement("li");
const listText = document.createElement("span");
const listBtn = document.createElement("button");
listItem.appendChild(listText);
listText.textContent = myItem;
listItem.appendChild(listBtn);
listBtn.textContent = "Delete";
list.appendChild(listItem);
生成的HTML结构:
<li>
<span>用户输入的项目名</span>
<button>Delete</button>
</li>
7.5 删除功能
listBtn.addEventListener("click", () => {
list.removeChild(listItem);
});
7.6 焦点管理
input.focus(); // 输入框重新获得焦点
});
7.7 完整代码
const list = document.querySelector("ul");
const input = document.querySelector("input");
const button = document.querySelector("button");
button.addEventListener("click", () => {
const myItem = input.value;
input.value = "";
const listItem = document.createElement("li");
const listText = document.createElement("span");
const listBtn = document.createElement("button");
listItem.appendChild(listText);
listText.textContent = myItem;
listItem.appendChild(listBtn);
listBtn.textContent = "Delete";
list.appendChild(listItem);
listBtn.addEventListener("click", () => {
list.removeChild(listItem);
});
input.focus();
});
执行流程图:
用户点击添加按钮
↓
① 保存 input.value → myItem
② 清空 input.value = ""
③ 创建 <li>、<span>、<button>
④ 设置 span.textContent = myItem
⑤ 设置 button.textContent = "Delete"
⑥ 组装:<li> → <span> + <button>
⑦ 添加到 <ul>
⑧ 为 button 绑定删除事件
⑨ input.focus()
总结
| 知识点 | 核心内容 |
|---|---|
| DOM本质 | HTML文档的树状结构表示,可编程操作的对象模型 |
| 浏览器三核心 | Window(全局环境)、Navigator(浏览器信息)、Document(DOM入口) |
| 现代选择方法 | querySelector() 选单个,querySelectorAll() 选所有 |
| 创建元素 | createElement() 内存中创建,appendChild() 添加到页面 |
| 移动元素 | appendChild() 操作同一实例,自动从原位置移动 |
| 删除元素 | parent.removeChild(child) 或 element.remove() |
| 样式操作 | element.style 设置内联样式,切换 class 更推荐 |
| CSS属性转换 | background-color → backgroundColor(小驼峰) |
| 实战模式 | 选择 → 创建 → 设置 → 组装 → 追加 → 事件绑定 |
掌握了这些基础能力后,开发者就具备了构建动态交互式网页的基本功。DOM编程的核心在于理解文档是一个可编程操作的对象结构——每一个HTML元素、每一段文本都是一个节点,JavaScript可以通过标准化的API来访问和修改这些节点。
还在为 JavaScript 代码写得像“意大利面条”、逻辑混乱难以维护而头秃?收藏本文持续跟进,后续将系统分享 JS 高效语法糖、浏览器兼容与 Polyfill 实战、手写核心源码解析、常见坑点避雷指南,从基础语法到进阶逻辑一站式打通,助你快速提升前端开发硬实力!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)