dom是浏览器解析html后生成的内存中树状对象模型,即“活文档”,以document为根节点,支持增删改查、事件绑定和样式控制。

DOM 不是 HTML 源代码,而是浏览器解析 HTML 后生成的内存中树状对象模型。你用 javaScript 操作的从来不是文本标签,而是这个实时、可交互的节点树。
DOM 是什么:浏览器里的“活文档”
HTML 文件只是静态文本;当浏览器加载它时,会构建一个由 document 对象为根的树形结构,每个标签(如
)、文本、甚至注释都变成一个“节点”。这个结构叫 DOM(Document Object Model),它支持增删改查、事件绑定、样式控制——全部通过 js 对象属性和方法完成。
获取元素:别只用
修改内容与属性:区分
关键点:
-
document是 DOM 的入口,所有操作起点都是它 - DOM 节点不是字符串,修改
innerHTML会重新解析并重建子节点,可能丢失事件监听器或表单状态 - DOM 变化会触发重排(reflow)和重绘(repaint),频繁操作需注意性能
获取元素:别只用 getElementById
现代开发中更常用语义清晰、灵活性高的方法:
立即学习“Java免费学习笔记(深入)”;
-
document.querySelector(".btn-primary"):返回第一个匹配 css 选择器的元素(支持类、属性、伪类等) -
document.querySelectorAll("input[type='text']"):返回nodelist,需用foreach或展开语法遍历 -
document.getElementById("header"):最快,但只能按 ID 查,且 ID 必须唯一、不能以数字开头 -
element.parentElement、element.children[0]等属性用于在已有节点基础上导航,避免重复查询
注意:querySelector 找不到时返回 NulL,直接调用 .innerText 会报 Cannot read Property 'innerText' of null —— 务必先判空。
修改内容与属性:区分 textContent 和 innerHTML
这是最常混淆的两个操作:
-
el.textContent = "Hello":把整个字符串当纯文本插入,显示为字面量Hello -
el.innerHTML = "Hello":解析 HTML,实际渲染加粗文字,但有 xss 风险,绝不能直接插入用户输入 - 设置属性优先用
el.setAttribute("disabled", "")或更直接的el.disabled = true(布尔属性推荐后者) - 读取自定义属性用
el.dataset.xxx(对应data-xxx),不用getAttribute
动态创建与插入:避免拼接长 HTML 字符串
用字符串拼接生成列表再赋给 innerHTML 看似简单,但易出错、难维护、有性能隐患。更稳妥的做法是:
- 用
document.createElement("li")创建新节点 - 用
li.textContent = item.name设置内容(安全) - 用
ul.appendChild(li)插入,或批量用DocumentFragment减少重排
const fragment = document.createDocumentFragment(); items.forEach(item => { const li = document.createElement("li"); li.textContent = item.name; fragment.appendChild(li); }); ul.appendChild(fragment);
如果必须用模板,建议搭配 template 标签或现代框架的编译机制,而不是手写字符串拼接。
真正难的不是“怎么写”,而是判断该不该操作 DOM —— 比如表单校验后聚焦错误字段,或动态加载内容后滚动到新区域,这些场景下 DOM 更新时机(如是否在 DOMContentLoaded 后)、节点是否已挂载、是否存在竞态,才是容易被跳过的复杂点。