DOM是浏览器将HTML转换成的JS可操作对象树,以document为根节点,包含元素、文本等节点;应优先用querySelector、classList、textContent等现代API安全高效操作。

DOM 不是某种独立技术,而是浏览器把 HTML 文档转换成的、可供 JavaScript 操作的对象树结构。它不是 HTML 本身,也不是 CSS,而是一套接口标准——只要浏览器实现了 DOM API,JS 就能用 document 对象去读取、修改、监听页面内容。
DOM 节点是怎么组织的?
HTML 中每个标签(比如 <div>、<p>)、文本、甚至注释,在 DOM 中都对应一个“节点”。最顶层是 document 对象,它是所有节点的根;往下是 document.documentElement(即 <html> 元素),再往下是 <head> 和 <body> 等元素节点。
关键点:
-
document.body是常用入口,但不要假设它一定存在——脚本若在<head>中执行,body可能还没解析完 - 文本内容属于
Text类型节点,不是Element,调用.innerHTML或.textContent才能安全读写 -
childNodes包含所有子节点(包括空白文本节点),而children只返回元素节点,日常操作优先用children
怎么查到想要的元素?
别硬遍历树,用现代选择器 API 直接定位:
立即学习“Java免费学习笔记(深入)”;
-
document.getElementById("id"):最快,但只能靠 ID,且 ID 必须唯一 -
document.querySelector("css-selector"):支持任意合法 CSS 选择器(如"nav a.active"、"[data-id='123']"),只返回第一个匹配项 -
document.querySelectorAll("css-selector"):返回NodeList,不是数组,但可用[...nodeList]展开或直接调用forEach - 避免用
getElementsByName或过时的getElementsByTagName,兼容性虽好,但表达力弱、返回动态集合易出错
改内容、加样式、删节点,怎么写才不翻车?
核心原则:少用 innerHTML,多用专一方法;改样式优先走 className 或 classList,而非拼字符串。
- 设文本内容:用
el.textContent = "xxx",而不是el.innerHTML = "xxx"—— 后者会触发 HTML 解析,有 XSS 风险,也更慢 - 加/删类名:用
el.classList.add("active")、el.classList.toggle("hidden"),比手动操作className字符串可靠得多 - 插入新元素:先用
document.createElement("div")创建,再用parent.appendChild(el)或parent.insertBefore(el, ref)插入;别直接拼 HTML 字符串后赋给innerHTML - 删除节点:没有
.remove()方法的老环境(IE)得写el.parentNode.removeChild(el);现代环境可直接用el.remove()
事件监听为什么总失效?
常见原因不是语法错,而是节点没找到,或监听时机不对:
- 脚本放在
<head>里,但 DOM 还没加载完 → 改用DOMContentLoaded事件包裹,或把 script 标签加defer - 元素是后续 JS 动态生成的 → 不要对它直接绑事件,改用事件委托:
document.addEventListener("click", e => { if (e.target.matches(".btn")) { ... } }) - 用了
onclick="..."行内绑定 → 很难维护,且无法用removeEventListener解绑;统一用addEventListener - 监听了冒泡阶段却调用
e.stopPropagation()过度 → 导致父级逻辑中断,除非明确需要,否则别轻易阻止冒泡
DOM 操作真正难的不是语法,而是对节点生命周期、事件流、重排重绘机制的理解。比如频繁修改 style 属性会强制同步计算样式,而批量操作 classList 或用 CSSOM 批量更新更高效。这些细节不写进控制台报错,但会让页面卡顿得莫名其妙。











