JavaScript DOM 核心操作:从内容到节点的实战指南(2025-2026实用版)
这是一份专门为真正要写业务代码的前端工程师准备的 DOM 操作核心知识浓缩版,重点突出高频、实用、容易出错的点。
一、DOM 节点获取(最常用8种方式对比)
| 方式 | 写法示例 | 性能 | 常用场景 | 备注与注意事项 |
|---|---|---|---|---|
| getElementById | getElementById('app') | ★★★★★ | ID 唯一元素 | 最快,几乎无兼容问题 |
| querySelector | querySelector('#app .list-item') | ★★★ | CSS 选择器风格 | 功能最强,但最慢 |
| querySelectorAll | querySelectorAll('.item') | ★★ | 获取多个 | 返回 NodeList(静态快照) |
| getElementsByClassName | getElementsByClassName('item') | ★★★★ | 纯类名查找 | 返回 HTMLCollection(动态集合) |
| getElementsByTagName | getElementsByTagName('div') | ★★★★ | 标签名查找 | 也是动态集合 |
| getElementsByName | getElementsByName('username') | ★★★ | 表单 name 属性 | 主要用于 input、textarea 等 |
| closest | el.closest('.modal') | ★★★ | 向上查找最近的祖先 | 非常实用,常用于事件委托 |
| matches | el.matches('.active') | ★★★ | 判断当前元素是否符合选择器 | 常用于条件判断 |
2025-2026推荐口诀:
能用 id 就 id → 不能用 id 再 querySelector → 大批量获取优先考虑 getElementsByClassName/TagName
二、节点创建与插入(高频操作全对比)
// 1. 最常用现代写法(推荐)
const div = document.createElement('div');
div.className = 'card';
div.textContent = 'Hello';
div.dataset.id = '123';
// 插入方式(性能从高到低大致排序)
parent.append(div); // 末尾追加(最推荐)
parent.prepend(div); // 开头插入
parent.appendChild(div); // 传统写法,等价于 append(单个元素)
parent.insertBefore(div, ref); // 在某个子节点前插入
parent.before(div); // 在 parent 前面插入
parent.after(div); // 在 parent 后面插入
// 2. 一次性插入大量内容(性能最佳)
const fragment = document.createDocumentFragment();
for(let i=0; i<100; i++){
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
list.appendChild(fragment); // 只引发一次重排
// 3. 危险但偶尔非常好用的写法
container.innerHTML += '<div>新内容</div>'; // ★会清空事件监听!慎用!
container.innerHTML = htmlString; // 更危险,会销毁所有子节点及事件
三、内容操作对比表(最容易搞混的几个)
| 属性/方法 | 读写内容包含什么 | 是否解析 HTML | 会破坏现有事件监听? | 推荐使用场景 |
|---|---|---|---|---|
| innerHTML | 包括所有 HTML 标签 | 是 | 是 | 需要插入/替换富文本时 |
| textContent | 只纯文本(不含标签) | 否 | 否 | 显示用户输入、安全首选 |
| innerText | 纯文本 + 考虑 CSS 显示 | 否 | 否 | 需要考虑 visibility/hidden 时 |
| nodeValue | 文本节点的内容 | 否 | 否 | 操作文本节点时 |
| insertAdjacentHTML | 在指定位置插入 HTML | 是 | 否(局部) | 局部插入 HTML 的最佳选择 |
推荐优先级(2026年):
显示用户输入/安全第一 → textContent
需要插入结构化 HTML → insertAdjacentHTML('beforeend', html)
必须完全替换内容 → innerHTML(谨慎)
四、节点关系导航(最实用总结)
el.parentElement // 父元素(最常用)
el.parentNode // 父节点(可能包含 DocumentFragment 等)
el.firstElementChild // 第一个子元素
el.lastElementChild // 最后一个子元素
el.children // 所有子元素(HTMLCollection)
el.nextElementSibling // 下一个兄弟元素
el.previousElementSibling // 上一个兄弟元素
el.childNodes // 所有子节点(包含文本节点、注释等)
el.firstChild / lastChild // 同上
五、经典真实业务场景代码片段(直接抄)
- 事件委托 + 动态列表项
document.querySelector('#user-list').addEventListener('click', e => {
const item = e.target.closest('.user-item');
if (!item) return;
const id = item.dataset.id;
const action = e.target.dataset.action;
if (action === 'delete') {
item.remove();
}
});
- 局部更新而不破坏事件
const container = document.querySelector('.comments');
container.insertAdjacentHTML('beforeend', newCommentHTML);
- 清空所有子元素最高效写法
// 推荐(最快)
while (container.firstChild) {
container.removeChild(container.firstChild);
}
// 或者(也很不错)
container.replaceChildren();
// 不要用(性能最差)
container.innerHTML = '';
六、2025-2026年 DOM 操作新趋势速览
- 大量使用
append/prepend/before/after/replaceChildren - 优先使用
closest()进行事件委托 - 尽量避免
innerHTML拼接,尤其是用户输入 - 更多使用 DocumentFragment + 批量插入
- 配合 Web Components / Lit / Alpine.js 等减少原生 DOM 操作
- Shadow DOM 越来越常见(尤其组件库)
一句话总结现代 DOM 操作心法:
“能批量就批量,能局部就局部,能文本用文本,能委托就委托,能不碰 innerHTML 就不碰。”
祝你写出又快又稳的前端代码!
需要针对某个具体业务场景(表格、表单、聊天列表、树形组件等)再深入写一套实战代码吗?可以直接告诉我~