原生JavaScript DOM操作实例:元素增删改查与事件监听

作者:像素猫

时间:2026-10-30

浏览:497

深入浅出讲解原生JavaScript中的DOM操作,通过完整实例解析元素的查找、创建、修改、删除以及事件监听与事件委托机制。

文章目录

在现代前端开发中,虽然各类响应式框架广泛普及,但理解并掌握原生JavaScript的DOM(文档对象模型)操作与事件监听机制,依然是每一位开发者解决复杂交互、优化渲染性能以及排查界面问题的基础能力。本文将直接围绕DOM树的查询、创建、修改、移除以及事件的捕获、冒泡与委托展开,结合可运行的代码实例解析核心API的具体用法与注意事项。

原生JavaScript DOM操作实例:元素增删改查与事件监听
图1:DOM 树形层级架构与核心容器节点关系图

一、元素查找(查)

DOM操作的第一步通常是精确定位目标节点。现代浏览器提供了强大的选择器API,使得我们可以直接使用CSS语法完成查询。

1. 常用查询方法

  • document.getElementById(id):依据唯一ID查找,性能极高,返回单个Element或null。
  • document.querySelector(selectors):返回文档中匹配指定CSS选择器的第一个元素,未找到则返回null。
  • document.querySelectorAll(selectors):返回匹配指定CSS选择器的静态NodeList集合。

2. 代码示例

// 1. 获取唯一容器
const appContainer = document.getElementById('app');

// 2. 使用 CSS 类选择器获取首个待办项
const firstTask = document.querySelector('.todo-item');

// 3. 获取所有待办列表项并进行遍历
const allTasks = document.querySelectorAll('#todo-list .todo-item');
allTasks.forEach(task => {
  console.log('任务文本:', task.textContent.trim());
});

注意:querySelectorAll 返回的是静态(non-live)集合,后续向DOM添加新元素并不会自动同步到已获取的集合中;而 getElementsByTagName 或 getElementsByClassName 返回的是动态集合(HTMLCollection),可能在循环遍历时引发意外行为,实际工程中推荐优先使用 querySelector 和 querySelectorAll。

二、元素创建与插入(增)

在页面中新增内容,包括创建新的元素节点、装配内容与属性,并将其挂载到现有DOM树上的指定位置。

原生JavaScript DOM操作实例:元素增删改查与事件监听
图2:DOM 节点创建、组装与挂载的执行顺序流程图

1. 核心挂载方法

  • document.createElement(tagName):根据标签名创建新的HTML元素。
  • parent.appendChild(childNode):将节点追加到指定父节点的子节点列表末尾。
  • parent.insertBefore(newNode, referenceNode):将新节点插入到父节点的某个已有子节点之前。
  • parent.append(...nodesOrDOMStrings):现代标准API,支持同时插入多个节点或字符串。

2. 代码示例

const listContainer = document.getElementById('todo-list');

// 批量添加任务项:使用 DocumentFragment 优化性能
const fragment = document.createDocumentFragment();

for (let i = 1; i <= 3; i++) {
  const item = document.createElement('li');
  item.className = 'todo-item';
  item.setAttribute('data-id', `task-${i}`);
  item.textContent = `待处理工作项目 #${i}`;

  // 创建子按钮
  const delBtn = document.createElement('button');
  delBtn.className = 'btn-delete';
  delBtn.textContent = '删除';
  item.appendChild(delBtn);

  fragment.appendChild(item);
}

// 一次性挂载到真实DOM树
listContainer.appendChild(fragment);

三、内容与属性修改(改)

对已有节点进行状态更新主要包括三个维度:文本与HTML内容修改、DOM样式与类名调整、以及元素HTML属性管理。

1. 核心操作维度

  • 文本与HTML内容:
    • node.textContent:安全设置纯文本内容,会对特殊符号进行自动转义,防止XSS注入。
    • node.innerHTML:用于解析HTML标签并重写内部结构。在包含用户不受信输入时必须严格审查,防范安全隐患。
  • 样式与类名:
    • node.classList.add(className) / remove() / toggle():推荐的类名管理方式。
    • node.style.property:设置行内样式,例如 node.style.backgroundColor = '#f0f0f0'。
  • 属性操作:
    • node.setAttribute('key', 'val') 与 node.getAttribute('key')。
    • node.dataset.customName:便捷读写 data-* 自定义属性。

2. 代码示例

const banner = document.querySelector('.banner-notice');

// 1. 安全修改纯文本
banner.textContent = '系统已完成版本更新,请刷新重试!';

// 2. 类名添加与切换
banner.classList.add('active');
banner.classList.toggle('warning-theme');

// 3. 读写自定义属性
banner.dataset.status = 'resolved';
console.log('当前状态标识:', banner.getAttribute('data-status'));

四、元素移除与替换(删)

在界面交互中,移除不再需要的节点或替换现有节点也是常见需求。

1. 移除与替换接口

  • childNode.remove():现代推荐API,节点自身直接调用即可从DOM中脱离。
  • parentNode.removeChild(childNode):经典兼容API,通过父节点指定移除子节点。
  • parentNode.replaceChild(newChild, oldChild):用新节点替换已有子节点。

2. 代码示例

// 方式一:直接移除自身
const notice = document.querySelector('.temporary-notice');
if (notice) {
  notice.remove();
}

// 方式二:父节点移除子项
const list = document.getElementById('todo-list');
const firstItem = list.firstElementChild;
if (firstItem) {
  list.removeChild(firstItem);
}

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

DOM不仅是静态的数据表现结构,还是用户与程序交互的桥梁。理解事件流的三个阶段(捕获阶段、目标阶段、冒泡阶段)是高效处理交互逻辑的前提。

原生JavaScript DOM操作实例:元素增删改查与事件监听
图3:DOM 事件流三阶段传播模型与事件委托机制示意图

1. 事件监听基础方法

标准监听方式为 addEventListener(type, listener, options)。第三个参数可选,布尔值或配置对象,useCapture: false 默认为冒泡监听。

2. 事件委托(Event Delegation)的优势

当一个列表中有成百上千个子项需要绑定事件,或者子项会频繁动态增删时,为每个子节点单独绑定事件监听器会导致内存占用显著增加,且新增加的节点需要重新绑定。利用事件冒泡机制,仅在共同的父容器上绑定单一监听器,通过检查 event.target 判断具体被点击的元素,不仅节省内存,还能自然支持动态添加的元素。

3. 综合实战代码:待办列表交互

// 获取列表父容器
const todoList = document.getElementById('todo-list');

// 在父容器上进行事件委托监听
todoList.addEventListener('click', function(event) {
  // 查找最近的按钮触发元素
  const deleteBtn = event.target.closest('.btn-delete');
  
  if (deleteBtn) {
    // 定位需要被删除的待办条目 li
    const listItem = deleteBtn.closest('.todo-item');
    if (listItem) {
      listItem.remove();
      console.log('已成功删除待办条目:', listItem.getAttribute('data-id'));
    }
    return;
  }

  // 点击列表项本身切换完成状态
  const listItem = event.target.closest('.todo-item');
  if (listItem) {
    listItem.classList.toggle('completed');
  }
});

六、DOM操作与性能总结

在日常开发中,直接操作DOM需要时刻注意性能开销与运行效率。DOM引擎与JavaScript引擎相互独立,每一次跨引擎访问和结构变动都会带来开销。合理利用批量操作和事件委托能够有效提升运行效率。

原生JavaScript DOM操作实例:元素增删改查与事件监听
图4:原生 JavaScript DOM 操作与事件监听总结矩阵表

掌握以上元素增、删、改、查及基于冒泡的事件委托机制后,开发者便能在没有外部类库依赖的环境下,编写出轻量、稳定且高效的前端交互界面。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章