DOM
DOM 是 HTML 文档的编程接口,它将网页表示为一个树形结构,其中每个节点都是文档的一个部分。
一、DOM 树结构
1. 基本概念
- DOM 树:将 HTML 文档表示为一个树形结构
- 节点(Node):树中的每个部分都是一个节点
- 元素节点:HTML 标签
- 文本节点:文本内容
- 属性节点:HTML 元素的属性
2. 节点类型
元素节点(Node.ELEMENT_NODE = 1)
- HTML 标签,如
<div>
、<p>
等 - 可以包含其他节点
- HTML 标签,如
文本节点(Node.TEXT_NODE = 3)
- 文本内容
- 不能包含其他节点
属性节点(Node.ATTRIBUTE_NODE = 2)
- HTML 元素的属性
- 如
class
、id
、style
等
注释节点(Node.COMMENT_NODE = 8)
- HTML 注释
文档节点(Node.DOCUMENT_NODE = 9)
- 整个文档的根节点
二、DOM 操作
1. 选择元素
// 1. 通过 ID 选择(返回单个元素)
const element = document.getElementById("myId");
// 2. 通过类名选择(返回 HTMLCollection)
const elements = document.getElementsByClassName("myClass");
// 3. 通过标签名选择(返回 HTMLCollection)
const elements = document.getElementsByTagName("div");
// 4. 通过 CSS 选择器选择
const element = document.querySelector(".myClass"); // 返回第一个匹配元素
const elements = document.querySelectorAll(".myClass"); // 返回 NodeList
2. 创建和修改元素
// 1. 创建元素
const div = document.createElement("div");
// 2. 添加文本内容
div.textContent = "Hello World";
// 3. 添加 HTML 内容
div.innerHTML = "<span>Hello</span>";
// 4. 设置属性
div.setAttribute("class", "myClass");
div.id = "myId";
// 5. 添加样式
div.style.color = "red";
div.style.backgroundColor = "blue";
// 6. 添加类名
div.classList.add("active");
div.classList.remove("active");
div.classList.toggle("active");
3. 添加和删除元素
// 1. 添加子元素
parent.appendChild(child);
// 2. 在指定元素前插入
parent.insertBefore(newChild, referenceChild);
// 3. 删除元素
parent.removeChild(child);
// 或
element.remove();
// 4. 替换元素
parent.replaceChild(newChild, oldChild);
4. 遍历 DOM
// 1. 获取父元素
const parent = element.parentNode;
const parentElement = element.parentElement; // 忽略文本节点
// 2. 获取子元素
const children = element.childNodes; // 包含文本节点
const children = element.children; // 只包含元素节点
const firstChild = element.firstChild;
const lastChild = element.lastChild;
// 3. 获取兄弟元素
const nextSibling = element.nextSibling;
const previousSibling = element.previousSibling;
三、事件处理
1. 事件绑定方式
// 1. HTML 内联方式(不推荐)
<button onclick="handleClick()">点击</button>
// 2. DOM 属性方式
element.onclick = function(event) {
console.log("Clicked!");
};
// 3. addEventListener 方式(推荐)
element.addEventListener("click", function(event) {
console.log("Clicked!");
});
// 4. 移除事件监听器
element.removeEventListener("click", handler);
2. 事件处理方式比较
HTML 内联方式
- 优点:简单直接
- 缺点:
- 违反关注点分离原则
- 不易维护
- 只能绑定一个处理函数
- 作用域混乱
DOM 属性方式
- 优点:简单,兼容性好
- 缺点:
- 只能绑定一个处理函数
- 可能被其他代码覆盖
addEventListener 方式
- 优点:
- 可以绑定多个处理函数
- 可以精确控制事件传播
- 支持事件委托
- 代码更清晰,易于维护
- 缺点:
- IE9 以下不支持(需要使用 attachEvent)
- 优点:
3. 常用事件
- click:点击
- mouseover:鼠标悬停
- mouseout:鼠标离开
- keydown:按键按下
- submit:表单提交
- load:页面加载完成
四、最佳实践
1. 性能优化
// 1. 缓存 DOM 查询结果
// 不好的做法
for (let i = 0; i < 100; i++) {
document.querySelector(".myClass").style.color = "red";
}
// 好的做法
const element = document.querySelector(".myClass");
for (let i = 0; i < 100; i++) {
element.style.color = "red";
}
// 2. 批量修改 DOM
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const div = document.createElement("div");
fragment.appendChild(div);
}
document.body.appendChild(fragment);
// 3. 使用事件委托
document.addEventListener("click", function(event) {
if (event.target.matches("button")) {
handleClick(event);
}
});
2. 注意事项
- innerHTML 比 textContent 慢,但可以插入 HTML
- 频繁的 DOM 操作会影响性能
- 注意内存泄漏,及时移除事件监听器
- 使用事件委托处理动态元素
- 注意跨浏览器兼容性