DOM用法指南
完整版:DOM 操作详解技术文档
一、DOM 概述
- DOM(Document Object Model):浏览器将 HTML/XML 文档解析后,生成的以节点(Node)为单位的树形结构。
- 目标:提供一组标准 API,通过脚本访问、修改、插入或删除文档内容和结构,实现页面动态互动。
DOM 树示例:
1
2
3
4
5
6
7
8
9Document
├─ html
├─ head
└─ body
├─ header
├─ main
│ ├─ section
│ └─ article
└─ footer二、DOM 节点类型
节点类型 常量 描述 元素节点 Node.ELEMENT_NODE
(1)<div>
,<p>
等标签文本节点 Node.TEXT_NODE
(3)标签或属性中的文本内容 属性节点 Node.ATTRIBUTE_NODE
(2)元素的属性,如 class="item"
注释节点 Node.COMMENT_NODE
(8)`<!-- 注释 -->
文档节点 Node.DOCUMENT_NODE
(9)`根节点,代表整个文档 三、节点选取(Selection)
1. 传统方法
1
2
3const el1 = document.getElementById('id');
const els1 = document.getElementsByClassName('class'); // HTMLCollection,返回页面上所有 class 名为 "class" 的元素。
const els2 = document.getElementsByTagName('div'); // HTMLCollection,返回页面上所有 <div> 标签元素假设你的 HTML 是这样:
1
2
3<div class="class">A</div>
<div class="class">B</div>
<div>C</div>你可以这样选取:
1
2
3
4
5
6const els1 = document.getEleme ntsByClassName('class'); // 包含 A 和 B
const els2 = document.getElementsByTagName('div'); // 包含 A、B 和 C
console.log(els1.length); // 输出 2
console.log(els2.length); // 输出 3
console.log(els1[0].textContent); // 输出 A2. CSS 选择器(推荐)
1
2const el2 = document.querySelector('.container > p'); // 第一个匹配元素
const allEls = document.querySelectorAll('ul li.active'); // NodeList区别:
HTMLCollection
实时更新,NodeList
静态(部分浏览器支持实时)。四、节点遍历(Traversal)
1
2
3
4
5
6const parent = el.parentNode; // 父节点
const children = el.childNodes; // 所有子节点(含文本、注释)
const first = el.firstChild; // 第一个子节点
const last = el.lastChild; // 最后一个子节点
const next = el.nextSibling; // 下一个同级节点
const prev = el.previousSibling; // 上一个同级节点遍历元素节点(忽略文本)可以用:
1
const childrenEls = el.children; // 只包含元素节点的 HTMLCollection
五、节点读取与写入(Read & Write)
1. 文本和 HTML 内容
1
2
3
4
5
6
7// 读取
let text = el.textContent; // 纯文本(包括子元素文本)
let html = el.innerHTML; // 包含子元素标签的 HTML
// 写入
el.textContent = '新文本'; // 自动转义,不会解析 HTML
el.innerHTML = '<strong>加粗文本</strong>'; // 插入 HTML 结构2. 属性与数据属性
1
2
3
4
5
6
7// 属性操作
el.setAttribute('data-id', '123');
let id = el.getAttribute('data-id');
el.removeAttribute('data-id');
// dataset 快捷访问
el.dataset.user = 'alice'; // 对应 data-user="alice"六、结构修改(Manipulation)
1. 创建与插入
1
2
3
4
5
6
7
8
9
10let newDiv = document.createElement('div');
newDiv.classList.add('card');
newDiv.textContent = '新卡片';
// append
document.body.appendChild(newDiv);
// insertBefore
let container = document.querySelector('#container');
container.insertBefore(newDiv, container.firstChild);2. 克隆与替换
1
2let clone = newDiv.cloneNode(true); // 深克隆(包含子节点)
container.replaceChild(clone, newDiv); // 替换节点3. 删除节点
1
2
3container.removeChild(clone);
// 或者
newDiv.remove(); // 现代浏览器可用七、CSS 样式与类名操作
1
2
3
4
5
6
7
8
9
10// 类名
el.classList.add('active');
el.classList.remove('hidden');
el.classList.toggle('open');
// 样式
el.style.width = '100px';
el.style.cssText += 'margin:10px; padding:5px;';
// 读取计算后的样式
let computed = window.getComputedStyle(el).display;八、事件绑定(Events)
1. 直接绑定
1
2
3
4function handleClick(e) {
console.log('Clicked:', e.target);
}
el.addEventListener('click', handleClick);2. 事件委托
1
2
3
4
5
6let list = document.querySelector('ul');
list.addEventListener('click', (e) => {
if (e.target.matches('li.item')) {
console.log('点击了列表项:', e.target.textContent);
}
});3. 移除监听器
1
el.removeEventListener('click', handleClick);
九、综合示例:动态图文列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<ul id="gallery"></ul>
const data = [
{ title: '图1', src: '1.jpg' },
{ title: '图2', src: '2.jpg' }
];
const gallery = document.getElementById('gallery');
// 使用 DocumentFragment 批量插入
let frag = document.createDocumentFragment();
data.forEach(item => {
let li = document.createElement('li');
let img = document.createElement('img'); img.src = item.src;
let caption = document.createElement('p'); caption.textContent = item.title;
li.appendChild(img);
li.appendChild(caption);
frag.appendChild(li);
});
gallery.appendChild(frag);十、性能优化与最佳实践
- 批量修改:使用
DocumentFragment
或模板字符串拼接后一次渲染。 - 节点缓存:频繁操作同一节点时,先查询并保存引用。
- 事件委托:避免大量子元素的单独监听。
- 最小重绘:减少对 layout 触发的读取/写入混合。
- 安全:避免直接插入未经过滤的用户内容,防范 XSS 攻击。
十一、总结
本档详细介绍了从节点类型、选取、遍历、读写到结构修改、样式、事件、性能等全方位的 DOM 操作技术。掌握这些知识,可帮助你构建交互丰富、高性能的网页应用。
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.