Skip to content

1.4 DOM 操作

DOM(Document Object Model,文档对象模型)是 HTML 文档的编程接口,JavaScript 通过 DOM 与 HTML 页面进行交互。

一、DOM 概述

什么是 DOM

DOM 是 HTML 文档的树状结构表示,JavaScript 可以通过 DOM 访问和修改页面内容。

HTML 文档
    └── 文档节点(document)
        └── html 元素
            ├── head 元素
            │   ├── title 元素
            │   └── ...
            └── body 元素
                ├── div 元素
                ├── p 元素
                └── ...

DOM 节点类型

  • 文档节点:document(整个文档的根节点)
  • 元素节点:HTML 标签(<div><p> 等)
  • 文本节点:元素内的文本内容
  • 属性节点:元素的属性(id、class 等)
  • 注释节点:HTML 注释

二、获取元素

1. 根据选择器获取(推荐)

javascript
// querySelector:获取匹配的第一个元素
const element = document.querySelector("#id");
const element = document.querySelector(".class");
const element = document.querySelector("div");
const element = document.querySelector("div.active");

// querySelectorAll:获取匹配的所有元素(NodeList)
const elements = document.querySelectorAll(".class");
const elements = document.querySelectorAll("ul li");

2. 根据ID获取

javascript
const element = document.getElementById("id");
// 返回单个元素或 null

3. 根据类名获取

javascript
const elements = document.getElementsByClassName("class");
// 返回 HTMLCollection(动态集合)

4. 根据标签名获取

javascript
const elements = document.getElementsByTagName("div");
const elements = document.getElementsByTagName("div")[0];
// 返回 HTMLCollection

5. 根据name属性获取

javascript
const elements = document.getElementsByName("username");
// 常用于表单元素

三、修改元素内容

1. 修改文本内容

javascript
const element = document.querySelector("div");

// innerText(只获取/设置可见文本)
console.log(element.innerText);
element.innerText = "新的文本";

// textContent(获取/设置所有文本,包括隐藏的)
console.log(element.textContent);
element.textContent = "新的文本";

2. 修改 HTML 内容

javascript
const element = document.querySelector("div");

// 获取/设置 HTML
console.log(element.innerHTML);
element.innerHTML = "<p>新的内容</p>";

// 设置纯文本(避免 XSS)
element.textContent = "<p>转义过的文本</p>";

// 插入 HTML
element.innerHTML += "<span>添加的元素</span>";

四、修改元素属性

1. 标准属性

javascript
const element = document.querySelector("img");

// 获取属性
const src = element.src;
const id = element.id;
const className = element.className;

// 设置属性
element.src = "new-image.jpg";
element.id = "new-id";
element.className = "new-class";

// classList(推荐)
element.classList.add("active");
element.classList.remove("active");
element.classList.toggle("active");
element.classList.contains("active");
element.className; // "active" 或 ""

2. 自定义属性

javascript
const element = document.querySelector("div");

// data- 属性
element.setAttribute("data-id", "123");
const dataId = element.getAttribute("data-id");

// dataset(推荐)
element.dataset.id = "123";
console.log(element.dataset.id); // "123"
element.dataset.userName = "张三";
console.log(element.dataset.userName); // "张三"

3. style 属性

javascript
const element = document.querySelector("div");

// 设置样式
element.style.color = "red";
element.style.fontSize = "20px";
element.style.backgroundColor = "#f0f0f0";

// 获取样式
console.log(element.style.color); // "red"

// 注意:style 只能获取/设置内联样式
const computedStyle = window.getComputedStyle(element);
console.log(computedStyle.color); // 获取计算后的样式

五、创建和插入元素

1. 创建元素

javascript
// 创建元素节点
const div = document.createElement("div");
const p = document.createElement("p");
const img = document.createElement("img");

// 创建文本节点
const text = document.createTextNode("这是一段文本");

// 创建文档片段(减少重排)
const fragment = document.createDocumentFragment();

2. 添加内容

javascript
const div = document.createElement("div");

// 设置文本
div.textContent = "标题";

// 设置 HTML
div.innerHTML = "<span>内容</span>";

// 添加文本节点
const text = document.createTextNode("文本");
div.appendChild(text);

3. 添加到页面

javascript
const parent = document.querySelector("container");
const child = document.createElement("div");
child.textContent = "子元素";

// appendChild(添加到最后)
parent.appendChild(child);

// prepend(添加到最前)
parent.prepend(child);

// insertBefore(指定位置插入)
const refElement = document.querySelector(".ref");
parent.insertBefore(child, refElement);

// insertAdjacentElement(灵活插入)
const element = document.createElement("div");
element.textContent = "新元素";

parent.insertAdjacentElement("beforebegin", element);  // 在父元素之前
parent.insertAdjacentElement("afterbegin", element);   // 在父元素第一个子元素之前
parent.insertAdjacentElement("beforeend", element);    // 在父元素之后
parent.insertAdjacentElement("afterend", element);     // 在父元素最后一个子元素之后

4. 替换和删除

javascript
const parent = document.querySelector("container");
const oldElement = document.querySelector(".old");
const newElement = document.createElement("div");
newElement.textContent = "新元素";

// 替换元素
parent.replaceChild(newElement, oldElement);

// 删除元素
oldElement.remove(); // 推荐方式
// parent.removeChild(oldElement); // 旧方式

六、节点关系

javascript
const element = document.querySelector("div");

// 父节点
console.log(element.parentNode);
console.log(element.parentElement); // 只返回元素节点

// 子节点
console.log(element.childNodes);    // 所有子节点(包括文本节点)
console.log(element.children);      // 只获取元素子节点

// 首尾子节点
console.log(element.firstChild);    // 第一个节点(可能是文本节点)
console.log(element.firstElementChild); // 第一个元素节点
console.log(element.lastChild);     // 最后一个节点
console.log(element.lastElementChild); // 最后一个元素节点

// 兄弟节点
console.log(element.previousSibling);     // 上一个兄弟节点
console.log(element.previousElementSibling); // 上一个兄弟元素节点
console.log(element.nextSibling);         // 下一个兄弟节点
console.log(element.nextElementSibling);     // 下一个兄弟元素节点

七、事件处理

1. 监听事件

javascript
const button = document.querySelector("button");

// addEventListener(推荐,可添加多个监听器)
button.addEventListener("click", function() {
    console.log("点击了按钮");
});

// 箭头函数
button.addEventListener("click", () => {
    console.log("箭头函数");
});

// 命名函数(可移除)
function handleClick() {
    console.log("命名函数");
}
button.addEventListener("click", handleClick);

// 事件对象
button.addEventListener("click", function(event) {
    console.log(event.type);     // 事件类型
    console.log(event.target);   // 触发元素
    console.log(event.currentTarget); // 绑定元素
});

2. 移除事件监听

javascript
button.removeEventListener("click", handleClick);

3. 事件冒泡与捕获

javascript
// 默认:冒泡(从内到外)
// 捕获:从外到内

// 冒泡阶段处理
element.addEventListener("click", handler, false);

// 捕获阶段处理
element.addEventListener("click", handler, true);

// 阻止冒泡
element.addEventListener("click", function(event) {
    event.stopPropagation();
});

4. 常用事件类型

javascript
const element = document.querySelector("div");

// 鼠标事件
element.addEventListener("click", () => {});       // 点击
element.addEventListener("dblclick", () => {});    // 双击
element.addEventListener("mousedown", () => {});   // 鼠标按下
element.addEventListener("mouseup", () => {});     // 鼠标松开
element.addEventListener("mouseenter", () => {});  // 鼠标进入
element.addEventListener("mouseleave", () => {});  // 鼠标离开
element.addEventListener("mousemove", () => {});   // 鼠标移动

// 键盘事件
window.addEventListener("keydown", (e) => {
    console.log(e.key);        // 按键名称
    console.log(e.keyCode);    // 按键代码
});
window.addEventListener("keyup", () => {});
window.addEventListener("keypress", () => {});

// 表单事件
const input = document.querySelector("input");
input.addEventListener("input", () => {});     // 输入
input.addEventListener("change", () => {});    // 改变
input.addEventListener("focus", () => {});     // 获得焦点
input.addEventListener("blur", () => {});      // 失去焦点

// 文档事件
window.addEventListener("load", () => {});             // 页面加载完成
window.addEventListener("DOMContentLoaded", () => {}); // DOM 加载完成
window.addEventListener("scroll", () => {});           // 滚动
window.addEventListener("resize", () => {});           // 调整窗口大小

八、表单操作

1. 获取表单元素

javascript
const form = document.querySelector("form");
const input = document.querySelector("input[type='text']");
const select = document.querySelector("select");
const textarea = document.querySelector("textarea");
const checkbox = document.querySelector("input[type='checkbox']");
const radio = document.querySelector("input[type='radio']");

2. 获取/设置值

javascript
const input = document.querySelector("input");

// 获取值
console.log(input.value);

// 设置值
input.value = "新值";

// 文本域
const textarea = document.querySelector("textarea");
textarea.value = "多行文本";

// 下拉选择
const select = document.querySelector("select");
console.log(select.value);
select.value = "option1";

// 复选框
const checkbox = document.querySelector("input[type='checkbox']");
console.log(checkbox.checked); // true/false
checkbox.checked = true;

// 单选框
const radios = document.querySelectorAll("input[name='gender']");
radios.forEach(radio => {
    if (radio.checked) {
        console.log(radio.value);
    }
});

3. 表单提交

javascript
const form = document.querySelector("form");

form.addEventListener("submit", function(event) {
    event.preventDefault(); // 阻止默认提交

    // 获取表单数据
    const formData = new FormData(form);
    const data = Object.fromEntries(formData);
    console.log(data);

    // 手动提交
    // form.submit();
});

九、常用方法

1. 类名操作

javascript
const element = document.querySelector("div");

element.classList.add("active");
element.classList.remove("active");
element.classList.toggle("active");
element.classList.contains("active");
element.classList.replace("old-class", "new-class");

2. 滚动操作

javascript
window.scrollTo(0, 0); // 滚动到顶部
document.querySelector("#section").scrollIntoView({ behavior: "smooth" });

// 获取滚动位置
console.log(window.scrollX);
console.log(window.scrollY);

3. 尺寸操作

javascript
const element = document.querySelector("div");

// 元素尺寸
console.log(element.offsetWidth);  // 包括 padding、border
console.log(element.offsetHeight);
console.log(element.clientWidth);   // 包括 padding
console.log(element.clientHeight);

// 位置
console.log(element.offsetLeft);
console.log(element.offsetTop);

总结

DOM 操作是前端开发的核心,熟练掌握各种方法可以高效地操作页面元素和实现交互效果。