引言:文档对象模型的重要性

在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-colorbackgroundColor(小驼峰)
实战模式 选择 → 创建 → 设置 → 组装 → 追加 → 事件绑定

掌握了这些基础能力后,开发者就具备了构建动态交互式网页的基本功。DOM编程的核心在于理解文档是一个可编程操作的对象结构——每一个HTML元素、每一段文本都是一个节点,JavaScript可以通过标准化的API来访问和修改这些节点。


还在为 JavaScript 代码写得像“意大利面条”、逻辑混乱难以维护而头秃?收藏本文持续跟进,后续将系统分享 JS 高效语法糖、浏览器兼容与 Polyfill 实战、手写核心源码解析、常见坑点避雷指南,从基础语法到进阶逻辑一站式打通,助你快速提升前端开发硬实力!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐