【Java Web学习 | 第12篇】JavaScript(6) – DOM(文档对象模型)深度详解(2026最新版)
恭喜你完成 BOM 部分!
现在进入 DOM(Document Object Model,文档对象模型),这是 JavaScript 操作 HTML 页面结构、内容和样式的核心技术。在 Java Web 项目中,DOM 操作是实现动态页面(如用户列表渲染、表单提交反馈、实时数据更新)的关键。
2026 年,DOM 操作依然以原生 API 为主,querySelector / querySelectorAll 是主流选择器,配合 DocumentFragment、事件委托、classList 等实现高性能更新。避免频繁直接操作 live DOM 是性能优化的核心原则。
1. DOM 核心概念
- DOM 是浏览器将 HTML 解析成的一个树状结构(节点树)。
- 节点类型:元素节点(Element)、文本节点(Text)、注释节点等。
- document 是 DOM 的入口对象。
console.log(document); // 整个文档
console.log(document.documentElement); // <html> 根元素
console.log(document.body); // <body>
2. 元素选择(Selection)—— 2026 推荐写法
// 1. 推荐:querySelector(返回第一个匹配元素)
const title = document.querySelector('h1');
const firstCard = document.querySelector('.card');
// 2. querySelectorAll(返回 NodeList,支持 forEach)
const cards = document.querySelectorAll('.card');
cards.forEach(card => {
card.style.border = '2px solid #007bff';
});
// 3. 传统方法(仍可用,但不推荐作为首选)
document.getElementById('userList');
document.getElementsByClassName('item');
document.getElementsByTagName('div');
// 最佳实践:缓存引用(避免重复查询)
const userList = document.querySelector('#userList'); // 缓存
性能提示:ID 最快,其次是类/标签。复杂选择器从右向左匹配,尽量简化。
3. 修改内容与属性
// 1. 文本内容(推荐 textContent,安全且快)
title.textContent = "Java Web 项目标题已更新";
// 2. HTML 内容(小心 XSS,信任数据时使用)
userInfo.innerHTML = `<strong>${username}</strong>`;
// 3. 属性操作
img.setAttribute('src', 'https://picsum.photos/300');
img.src = 'https://picsum.photos/300'; // 常用属性可直接操作
// 4. class 操作(强烈推荐 classList)
element.classList.add('active');
element.classList.remove('inactive');
element.classList.toggle('dark-mode');
element.classList.contains('highlight'); // 返回 boolean
4. 创建、添加与删除元素(动态渲染核心)
// 创建元素
const newDiv = document.createElement('div');
newDiv.className = 'user-item';
newDiv.innerHTML = `<h3>${user.username}</h3><p>年龄:${user.age}</p>`;
// 添加到文档
document.body.appendChild(newDiv); // 追加到末尾
parentElement.append(newDiv); // 现代写法,支持多个
parentElement.prepend(newDiv); // 插入到开头
// 批量插入性能优化:使用 DocumentFragment
function renderUserList(users) {
const fragment = document.createDocumentFragment(); // 轻量容器,不触发重绘
users.forEach(user => {
const item = document.createElement('div');
item.className = 'user-item';
item.textContent = user.username;
fragment.appendChild(item);
});
userList.innerHTML = ''; // 清空原有
userList.appendChild(fragment); // 一次性插入,只触发一次重绘
}
5. 事件处理(Event)—— 动态交互基础
// 1. 推荐:addEventListener(支持多个监听器)
const btn = document.querySelector('#submitBtn');
btn.addEventListener('click', (event) => {
console.log('按钮被点击');
event.preventDefault(); // 阻止默认行为(如表单提交)
});
// 2. 事件委托(性能最佳实践,大量子元素时推荐)
userList.addEventListener('click', (e) => {
if (e.target.closest('.delete-btn')) { // 委托到父元素
const item = e.target.closest('.user-item');
item.remove(); // 删除元素
console.log('删除成功');
}
});
常用事件:click、input、submit、keydown、load、resize 等。
6. 遍历与节点关系
// 子节点
const children = parent.children; // HTMLCollection(仅元素节点)
const childNodes = parent.childNodes; // NodeList(包含文本节点)
// 父/兄弟节点
element.parentElement;
element.nextElementSibling;
element.previousElementSibling;
7. 完整实战示例:动态用户列表(结合后端数据准备)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>DOM 实战 - 用户列表</title>
<style>
.user-item { padding: 15px; margin: 8px 0; background: #f8f9fa; border-radius: 8px; }
.delete-btn { color: red; margin-left: 10px; }
</style>
</head>
<body>
<h1>用户管理</h1>
<button id="addBtn">添加用户</button>
<div id="userList"></div>
<script>
const users = [
{ id: 1, name: "张三", age: 25 },
{ id: 2, name: "李四", age: 30 }
];
const userList = document.getElementById('userList');
const addBtn = document.getElementById('addBtn');
function renderUsers() {
const fragment = document.createDocumentFragment();
users.forEach(user => {
const div = document.createElement('div');
div.className = 'user-item';
div.innerHTML = `
${user.name}(${user.age}岁)
<button class="delete-btn" data-id="${user.id}">删除</button>
`;
fragment.appendChild(div);
});
userList.innerHTML = '';
userList.appendChild(fragment);
}
// 事件委托
userList.addEventListener('click', (e) => {
if (e.target.classList.contains('delete-btn')) {
const id = parseInt(e.target.dataset.id);
const index = users.findIndex(u => u.id === id);
if (index > -1) users.splice(index, 1);
renderUsers();
}
});
addBtn.addEventListener('click', () => {
const newUser = { id: Date.now(), name: "新用户", age: 28 };
users.push(newUser);
renderUsers();
});
// 初始化
renderUsers();
</script>
</body>
</html>
8. 2026 DOM 操作最佳实践
- 缓存元素引用:避免重复
querySelector。 - 批量更新:使用
DocumentFragment或innerHTML(数据可信时)。 - 事件委托:减少监听器数量。
- 避免强制重排:批量读写分离,必要时用
requestAnimationFrame。 - 现代替代:复杂场景可考虑 Web Components / Shadow DOM,但原生 DOM 仍是基础。
- 性能工具:浏览器 DevTools(Performance 面板)分析重绘/重排。
9. 小练习(立即动手)
- 创建一个按钮,点击后动态添加一个带随机颜色的
<div>到页面。 - 实现一个待办事项列表:输入内容后添加,点击项可删除(使用事件委托)。
- 用
querySelectorAll获取所有.card,给它们添加hover效果(通过 classList)。 - 修改上面的用户列表示例,添加“编辑”按钮(点击弹出 prompt 修改名称)。
下一篇文章预告:《【Java Web学习 | 第13篇】JavaScript(7) – 异步编程(Promise + async/await)与 Fetch API》
我们将学习现代异步机制,并使用 fetch 真正调用 Spring Boot 后端 REST 接口,实现数据增删改查。
本篇核心总结:
- 选择器:优先
querySelector/querySelectorAll - 修改:
textContent(安全)、classList(优雅) - 批量:
DocumentFragment - 事件:
addEventListener+ 委托
有问题随时问:
- 想要更多性能优化示例(如虚拟列表)?
- 需要完整购物车 / 表单验证 DOM 实战?
- 或直接进入 异步 + Fetch 篇?
回复“给我练习答案”或“下一篇 Fetch”,我立刻继续!
DOM 是 JavaScript 操作页面的“双手”,掌握后你已经可以构建动态交互界面。继续加油,下一章我们就要和后端真正交互了!🚀