dom核心
约 2681 字大约 9 分钟
2026-03-19
手写笔记



一、Web API概述
1.1 标准库与Web API的区别
- Q:标准库和Web API有什么区别?
- A:
- 标准库:ECMAScript规定的对象和函数(如
Array/Object/Math等),与运行环境无关,在任何支持ES的环境中都能使用。 - Web API:浏览器宿主环境提供的对象和函数,由W3C等组织制定,是浏览器为JS提供的额外能力,核心分为两类:
- BOM (Browser Object Model):浏览器对象模型,用于操作浏览器窗口、导航、历史记录等。
- DOM (Document Object Model):文档对象模型,用于操作HTML/XML文档的结构和内容。
- 标准库:ECMAScript规定的对象和函数(如
1.2 DOM版本演进
DOM标准的发展历程:DOM0 → DOM1 → DOM2 → DOM3 → DOM4(2015年发布)
1.3 DOM核心概念
- Q:什么是DOM?
- A:DOM是将HTML/XML文档用对象模型表示的一种方式,它把整个文档解析成一个由节点组成的树形结构,每个文档内容都是一个
Node(节点对象),所有DOM操作都是对节点对象的操作。
常见节点类型:
| 节点类型 | 说明 |
|---|---|
DocumentType | 文档类型节点(如<!DOCTYPE html>) |
Document | 文档节点,代表整个文档(全局document对象) |
Comment | 注释节点 |
Element | 元素节点(如<div>/<p>等HTML标签) |
Text | 文本节点 |
Attribute | 属性节点(如class="box") |
DocumentFragment | 文档片段节点(轻量级容器,用于批量操作DOM优化性能) |
二、获取DOM节点
2.1 获取DOM根对象
全局对象window上的document属性代表整个文档节点,是所有DOM操作的入口。
2.2 旧的获取元素节点方式(DOM0)
| 方法 | 说明 |
|---|---|
document.body | 获取<body>元素节点 |
document.head | 获取<head>元素节点 |
document.links | 获取页面所有超链接元素节点(返回类数组对象) |
document.anchors | 获取页面所有带name属性的锚点元素节点 |
document.forms | 获取页面所有<form>表单元素节点 |
2.3 新的获取元素节点方式
根据方法获取
| 方法 | 语法 | 说明 |
|---|---|---|
getElementById(id) | document.getElementById("box") | 通过ID获取对应元素,执行效率最高 |
getElementsByTagName(tag) | document.getElementsByTagName("div") | 通过标签名获取元素集合(实时更新) |
getElementsByClassName(class) | document.getElementsByClassName("item") | 通过类名获取元素集合(实时更新,IE9+支持) |
querySelector(selector) | document.querySelector(".box") | 通过CSS选择器获取第一个匹配的元素(IE8+支持) |
querySelectorAll(selector) | document.querySelectorAll(".item") | 通过CSS选择器获取所有匹配的元素(静态集合,非实时) |
document.documentElement | - | 获取根元素<html> |
重要细节扩展
- 实时集合 vs 静态集合:
- 除
querySelectorAll外,其他获取集合的方法(getElementsByXXX)返回的是实时集合,当文档结构变化时,集合会自动更新。 querySelectorAll返回静态集合,不会随文档变化自动更新。
- 除
- ID重复问题:若多个元素有相同ID,
getElementById只会返回第一个;且ID元素会自动成为window的属性,不推荐依赖此特性。 - 上述所有方法也可作为其他元素节点对象的方法使用(如
element.querySelector()),表示在该元素内部查找匹配的节点。
2.4 根据节点关系获取节点
| 方法 | 说明 | 扩展 |
|---|---|---|
parentNode | 获取父节点(可能是元素或文档节点) | 可能获取到非元素节点,实际开发中较少使用 |
previousSibling | 获取上一个兄弟节点 | 可能获取到文本或注释节点 |
nextSibling | 获取下一个兄弟节点 | 可能获取到文本或注释节点 |
childNodes | 获取所有子节点 | 包含文本、注释节点,实时更新 |
firstChild | 获取第一个子节点 | 可能获取到文本或注释节点 |
lastChild | 获取最后一个子节点 | 可能获取到文本或注释节点 |
attributes | 获取某元素的所有属性节点 | 返回实时集合 |
| --- | --- | --- |
parentElement | 获取父元素节点 | 只返回元素节点,开发中更常用 |
previousElementSibling | 获取上一个兄弟元素 | 只返回元素节点 |
nextElementSibling | 获取下一个兄弟元素 | 只返回元素节点 |
children | 获取所有子元素 | 只返回元素节点,实时更新 |
firstElementChild | 获取第一个子元素 | 只返回元素节点 |
lastElementChild | 获取最后一个子元素 | 只返回元素节点 |
三、获取DOM节点信息
3.1 节点通用属性
所有节点对象都包含以下三个核心属性,用于区分节点类型和获取节点信息:
| 属性 | 说明 |
|---|---|
nodeName | 获取节点名称(元素节点返回大写标签名,如DIV;文本节点返回#text) |
nodeValue | 获取节点的值(文本/注释节点返回内容,元素节点返回null) |
nodeType | 节点类型(数字标识:1=元素节点,3=文本节点,8=注释节点) |
四、DOM元素操作
4.1 初识元素事件
- 元素事件:某个元素上发生的特定动作(如点击、输入、页面加载等)。
- 事件处理程序:一个函数,定义了当事件发生时需要执行的操作。
- 注册事件:将事件处理程序与元素的特定事件关联起来的过程。
this指向规则:在事件处理程序中,this默认指代当前触发事件的元素对象。
4.2 获取和设置元素属性
通用属性操作方式
| 方法 | 说明 |
|---|---|
getAttribute(attrName) | 获取指定属性的值 |
setAttribute(attrName, value) | 设置指定属性的值 |
removeAttribute(attrName) | 删除指定属性 |
可识别属性的直接访问方式
- 语法:
dom.属性名(如dom.className/dom.src/dom.id) - 与通用方式的区别:
- 对于HTML标准属性,即使没有显式赋值,也会有默认值(如
input.value默认为空字符串)。 - 布尔属性在DOM对象中会自动转换为布尔值(如
button.disabled)。 - 部分属性名与JS标识符冲突,需要使用别名(如
class属性对应className,for属性对应htmlFor)。
- 对于HTML标准属性,即使没有显式赋值,也会有默认值(如
自定义属性操作
- HTML5规范建议自定义属性使用
data-前缀(如<div data-user-id="123" data-user-name="张三">)。 - 访问方式:通过
dom.dataset.属性名访问(驼峰命名,如dom.dataset.userId)。 - 删除方式:
delete dom.dataset.属性名。
4.3 获取和设置元素内容
| 属性 | 说明 |
|---|---|
innerHTML | 获取/设置元素内部的HTML文本,会解析其中的HTML标签 |
innerText | 获取/设置元素内部的纯文本,仅返回页面上可见的文本,会忽略标签和隐藏元素 |
textContent | 获取/设置元素内部的纯文本,包含所有文本内容(包括隐藏元素的文本),不会解析HTML标签 |
⚠️ 安全提示:使用
innerHTML设置内容时,若内容包含用户输入的不可信数据,会存在XSS(跨站脚本攻击)风险,应尽量避免使用,或对内容进行严格转义。
4.4 元素结构重构
以下方法会直接修改DOM树结构,频繁调用会导致页面重绘重排,影响性能,应尽量减少使用:
| 方法 | 语法 | 说明 |
|---|---|---|
appendChild(child) | parent.appendChild(child) | 将子元素添加到父元素的末尾 |
insertBefore(newChild, refChild) | parent.insertBefore(newChild, refChild) | 将新子元素插入到参考子元素之前 |
replaceChild(newChild, oldChild) | parent.replaceChild(newChild, oldChild) | 用新子元素替换旧子元素 |
4.5 创建、删除与克隆元素
| 方法 | 语法 | 说明 |
|---|---|---|
createElement(tag) | document.createElement("div") | 创建一个新的元素对象 |
createTextNode(text) | document.createTextNode("hello") | 创建一个文本节点 |
createDocumentFragment() | document.createDocumentFragment() | 创建文档片段(轻量级容器,批量操作DOM时可显著优化性能) |
cloneNode(deep) | dom.cloneNode(true) | 克隆DOM对象,true表示深度克隆(包含所有子节点),false表示浅克隆(仅克隆自身) |
removeChild(child) | parent.removeChild(child) | 父元素调用,移除指定的子元素 |
remove() | dom.remove() | 元素自己删除自己(现代浏览器支持,IE不支持) |
💡 性能优化技巧:批量添加多个DOM元素时,先将所有元素添加到
DocumentFragment中,再将DocumentFragment一次性添加到页面,可减少重绘重排次数。
五、DOM元素样式
5.1 控制元素类名
| 方法/属性 | 说明 |
|---|---|
className | 获取/设置元素的类名字符串,多个类名用空格分隔 |
classList | DOM4新增属性,是一个专门用于控制类名的对象,提供以下方法: ① add(className):添加一个或多个类名② remove(className):移除一个或多个类名③ contains(className):判断是否包含指定类名④ toggle(className):切换类名(存在则移除,不存在则添加) |
💡 推荐使用
classList控制元素类名,比直接操作className更简洁、更安全。
5.2 获取元素样式
注意:CSS中的短横线命名在JS中需要转换为小驼峰命名(如
font-size→fontSize,background-color→backgroundColor)。
| 方法 | 说明 |
|---|---|
dom.style | 获取元素的行内样式对象,只能获取和设置行内样式,无法获取内部样式表和外部样式表的样式 |
window.getComputedStyle(dom, pseudoElt) | 获取元素的最终计算样式,包含所有样式来源(行内、内部、外部、浏览器默认样式);第二个参数可选,用于获取伪元素的样式 |
5.3 设置元素样式
- 语法:
dom.style.样式名 = "值" - 说明:通过
style属性设置的是行内样式,优先级最高。 - 示例:
const box = document.getElementById("box"); box.style.fontSize = "20px"; box.style.backgroundColor = "#ff0000"; box.style.marginTop = "10px";
六、作业讲解:拼图游戏
6.1 项目介绍
- 实践项目:通过DOM操作实现经典拼图游戏
- 核心知识点:元素拖拽实现、元素位置交换、样式动态控制、事件处理
- 综合运用:节点获取与操作、事件注册与处理、样式控制、数组操作等知识
七、核心总结
- Web API与DOM本质:Web API是浏览器提供的额外能力,分为BOM和DOM;DOM将文档抽象为节点树,所有操作围绕节点对象展开。
- 节点获取:优先使用
querySelector和querySelectorAll,注意区分实时集合与静态集合的差异;根据节点关系获取时,优先使用只返回元素节点的方法。 - 元素操作:掌握属性、内容、结构的操作方法,注意
innerHTML的XSS安全风险;批量操作DOM时使用DocumentFragment优化性能。 - 样式控制:优先通过
classList控制类名来改变样式,避免直接操作style;获取元素最终样式使用getComputedStyle。 - 性能优化:减少DOM树的修改次数,避免频繁重绘重排,是前端性能优化的重要方向。
