常用JavaScript DOM操作方法汇总与实例

作者:页面旅途时间:2026-10-30 19:08:26浏览:406

系统整理常用JavaScript DOM操作方法,包括元素选取、节点增删改查、内容与属性操作、样式控制以及事件委托,配合完整代码示例与高清内联SVG图解。

文档对象模型(DOM)是浏览器将 HTML 文档抽象为层级对象树的编程接口。在现代前端开发中,虽然前端框架封装了大量底层细节,但直接、准确地掌握原生 JavaScript DOM 操作方法,依然是理解网页交互逻辑、排查渲染瓶颈以及编写轻量独立组件的立足之本。本文紧扣常用 DOM API,围绕节点查询、结构增删、属性与内容更新、样式控制以及事件监听五个维度展开系统汇总,并配合实际应用场景代码与结构图示进行说明。

一、元素选取与节点查询

DOM 树上的每个 HTML 标签、属性和文本都被表达为特定类型的节点。要对页面进行交互改造,第一步是在树形结构中定位到目标节点。在现代标准中,推荐优先使用语义明确的选择器方法。

1. 精准定位与全量检索

  • document.getElementById(id):通过唯一 ID 查找元素。该方法直接利用浏览器内部的 ID 哈希索引,查询速度极快,未找到时返回 null。
  • document.querySelector(selector):使用 CSS 选择器语法查询第一个匹配项。支持类名、属性选择器、层级结构等任意合法 CSS 规则,灵活性极高。
  • document.querySelectorAll(selector):返回匹配 CSS 选择器的所有元素集合。该集合是一个静态 NodeList(节点快照),其内容不会因后续 DOM 结构的动态改变而意外变动。
常用JavaScript DOM操作方法汇总与实例
图 1:DOM 树层级与常用选择器查询路径

2. 关系遍历与上下文匹配

除了从根部全文档检索,基于已知节点向周围导航往往更加轻量高内聚:

  • element.closest(selector):从当前元素自身开始向上逐级检查祖先链,返回最近匹配选择器的祖先元素。该方法在事件委托处理中不可或缺。
  • element.matches(selector):检验当前元素自身是否满足某 CSS 选择器,返回布尔值。
  • element.parentElement、element.children、element.nextElementSibling:纯元素维度的相对节点检索,可自动跳过空白符文本节点。
// 示例:查找与条件验证
const activeCard = document.querySelector('.card.active');
if (activeCard) {
  // 向上寻找最近的容器列表
  const section = activeCard.closest('section[data-group]');
  // 检查自身是否带有特别标识
  const isFeatured = activeCard.matches('.featured');
  console.log('所属分组:', section?.dataset.group, '是否特选:', isFeatured);
}

二、节点的创建、组装与挂载

向页面动态增加内容是交互系统的核心功能。从技术流程上,节点的添加需要经过“内存中创建”、“装配属性内容”以及“挂载接入文档树”三个标准步骤。

常用JavaScript DOM操作方法汇总与实例
图 2:DOM 节点创建与挂载标准工作流程

1. 核心挂载与删除方法对比

方法名称 调用主体 参数特性 主要场景
document.createElement(tagName) document 标签名称字符串 在内存中生成新的孤立 Element 节点
parent.append(...nodesOrDOMStrings) 父元素 支持多个节点或纯文本字符串 现代挂载 API,末尾追加多个元素
parent.prepend(...nodesOrDOMStrings) 父元素 支持多个节点或纯文本字符串 在父元素首个子节点之前插入内容
parent.insertBefore(newNode, refNode) 父元素 新节点, 参考基准子节点 在指定的特定兄弟节点前精确插入
element.remove() 待删除元素自身 无参数 直接将当前节点从其所属父级中剔除

2. 高性能批量插入实例(使用 DocumentFragment)

如果需要在循环中插入成百上千个 DOM 元素,直接在每次循环中执行 parent.appendChild() 会导致浏览器频繁计算页面布局(引发多次重排)。此时应使用 DocumentFragment:

// 业务场景:批量生成任务列表项
const taskData = ['代码规范审查', '单元测试覆盖', '构建体积分析', 'CDN发布部署'];
const listContainer = document.getElementById('task-list');

// 1. 创建内存中的虚拟文档片段
const fragment = document.createDocumentFragment();

taskData.forEach((taskTitle, index) => {
  // 2. 依次生成并装配子节点
  const li = document.createElement('li');
  li.className = 'task-item';
  li.dataset.index = String(index);
  li.textContent = taskTitle;

  // 3. 追加至片段中(不触发重排)
  fragment.appendChild(li);
});

// 4. 一次性接入页面真实 DOM(仅引发 1 次重排)
listContainer.appendChild(fragment);

三、元素内容、属性与样式操作

节点挂载后,页面内容的动态变化通常涉及对其内部文本、原生/自定义属性以及表现样式的修改。正确理解这些操作的边界,能够避免常见的安全隐患与样式冲突。

常用JavaScript DOM操作方法汇总与实例
图 3:DOM 元素内容、属性与样式操作对比模型

1. 内容注入:textContent 与 innerHTML

当只需要展示纯文本信息(如用户昵称、数值、提示文案)时,必须始终使用 textContent。textContent 会自动将输入中的特殊字符进行实体编码,从机制上杜绝恶意脚本注入(XSS 漏洞)。只有在明确需要解析并渲染受信任的 HTML 富文本标记时,才考虑使用 innerHTML。

2. classList 状态管理 API

避免直接使用字符串拼接修改 element.className,这极易误删已有样式类。现代开发统一采用 classList 接口:

  • element.classList.add('active', 'loading'):添加一个或多个类名。
  • element.classList.remove('hidden'):移除指定类名。
  • element.classList.toggle('collapsed', forceBoolean):类名存在则移除,不存在则添加;支持传入第二个布尔参数进行强制开关。
  • element.classList.contains('active'):检查是否拥有某类名,返回布尔值。
// 实例:卡片展开收起交互组件
const toggleButton = document.querySelector('#toggle-btn');
const detailPanel = document.querySelector('#detail-panel');

toggleButton.addEventListener('click', () => {
  // 1. 切换类名状态
  const isExpanded = detailPanel.classList.toggle('is-open');

  // 2. 更新 ARIA 辅助可访问性属性
  toggleButton.setAttribute('aria-expanded', String(isExpanded));

  // 3. 安全更新按钮文字
  toggleButton.textContent = isExpanded ? '收起详情' : '展开详情';
});

四、事件监听与事件委托机制

静态的页面结构依赖事件系统实现与用户的即时交互。现代标准采用 addEventListener 注册监听器,支持事件流完整生命周期管理。

1. 标准事件监听规范

注册与解绑的基本规范如下:

function handleResize() {
  console.log('窗口尺寸变动:', window.innerWidth);
}

// 注册监听器
window.addEventListener('resize', handleResize);

// 解绑监听器(必须传入具名函数的引用,匿名函数无法解绑)
window.removeEventListener('resize', handleResize);

2. 高性能事件委托模式(Event Delegation)

当页面存在大量相似子节点(如长列表、商品网格)或者子节点会动态新增时,逐个为每个子元素绑定 click 监听器会占用大量内存,且新插入的节点无法自动响应事件。根据浏览器事件冒泡机制,我们可以仅在共同的父容器上绑定一次监听器,通过检查 event.target 来识别触发源:

// 业务场景:动态购物车列表的事件委托
const cartContainer = document.querySelector('#cart-items');

cartContainer.addEventListener('click', (event) => {
  // 向上定位被点击的动作按钮
  const actionBtn = event.target.closest('button[data-action]');
  if (!actionBtn || !cartContainer.contains(actionBtn)) return;

  // 定位按钮所属的行容器
  const itemRow = actionBtn.closest('.cart-row');
  const itemId = itemRow?.dataset.id;
  const actionType = actionBtn.dataset.action;

  switch (actionType) {
    case 'delete':
      itemRow.remove(); // 直接删除节点
      break;
    case 'increase':
      const countEl = itemRow.querySelector('.count');
      countEl.textContent = String(Number(countEl.textContent) + 1);
      break;
  }
});

注意区分:在事件回调中,event.target 表示实际触发事件的最底层元素(用户鼠标真正点到的节点),而 event.currentTarget 则代表绑定当前事件监听器的元素(上述例子中的 cartContainer)。

五、全景体系总结与避坑清单

为了在实际编码中更清晰地建立知识联系,下图将原生 JavaScript DOM 操作的核心知识域与高频 API 进行了汇总:

常用JavaScript DOM操作方法汇总与实例
图 4:JavaScript 常用 DOM 操作 API 全景体系

开发避坑要点

  1. 缓存查询结果:避免在 for 循环或高频 scroll/mousemove 事件内部重复执行 document.querySelector,应在循环外部将节点缓存到变量中。
  2. 避免强制同步布局(Layout Thrashing):不要在修改完样式(如写入 element.style.width)后立即读取几何计算属性(如 element.offsetWidth),这会强迫浏览器提前重排。推荐先批量读取,再批量写入。
  3. 防范内存泄露:为动态元素绑定监听器时,若不使用事件委托,在通过 remove() 销毁节点前最好显式调用 removeEventListener 解绑依赖外部闭包的监听函数。
作者最新文章
相关文章
更多