前端三基石(三) JavaScript DOM 操作与事件处理
目录前言一、DOM 是什么二、获取元素2.1 传统方法2.2 选择器方法推荐三、操作元素内容3.1 innerHTML3.2 textContent vs innerText四、操作元素属性4.1 标准属性4.2 自定义属性五、操作元素样式5.1 style 属性5.2 classList推荐六、动态创建与删除元素6.1 创建元素6.2 添加元素6.3 删除元素七、事件处理7.1 事件绑定方式7.2 常用事件7.3 事件对象7.4 事件委托八、总结前言在上一篇中我们掌握了 JavaScript 的核心语法——变量、函数、对象、运算符等。但学会语法只是第一步JavaScript 在浏览器中的真正威力在于操作网页元素、响应用户交互。这需要理解 DOMDocument Object Model——浏览器提供给 JS 操作网页的接口。本文是前端三基石系列第二篇的续篇聚焦 DOM 操作与事件处理。一、DOM 是什么DOM 是浏览器将 HTML 解析成的一棵节点树htmlheadtitle示例/title/headbodydividcontainerpclasstextHello/p/div/body/html浏览器会将其解析为Document └── html ├── head │ └── title └── body └── div#container └── p.text └── Hello每个 HTML 标签都是一个元素节点文本内容是文本节点。JS 通过document对象访问这棵树。后端类比DOM 类似于 Java 解析 XML 的 DOM 模型——把文档结构化为对象树通过 API 增删改查节点。二、获取元素操作元素的第一步是找到它。2.1 传统方法// 通过 id 获取唯一document.getElementById(container);// 通过标签名获取返回集合document.getElementsByTagName(div);// 通过类名获取返回集合document.getElementsByClassName(text);这些方法返回的是HTMLCollection是活的集合——文档变化时自动更新。2.2 选择器方法推荐ES5 提供了更灵活的选择器方法// 获取单个元素第一个匹配的document.querySelector(#container);document.querySelector(.text);document.querySelector(div p);// 获取所有匹配的元素返回 NodeListdocument.querySelectorAll(.text);document.querySelectorAll(div p);方法返回值特点querySelector()单个元素找不到返回nullquerySelectorAll()NodeList找不到返回空列表不是null推荐使用选择器方法语法统一与 CSS 选择器一致代码更清晰。三、操作元素内容3.1 innerHTML读取或设置元素的 HTML 内容dividboxspanHello/span/divscriptconstboxdocument.getElementById(box);// 读取得到 HTML 字符串console.log(box.innerHTML);// \n spanHello/span\n// 设置会解析 HTMLbox.innerHTMLstrongWorld/strong;/script安全警告不要将用户输入直接赋值给innerHTML会导致 XSS 攻击// 危险用户输入可能包含恶意脚本box.innerHTMLuserInput;// ❌// 安全的方式使用 textContentbox.textContentuserInput;// ✅3.2 textContent vs innerText两者都操作纯文本但有区别dividboxstyledisplay:noneHellospanWorld/span/divscriptconstboxdocument.getElementById(box);console.log(box.textContent);// Hello World获取所有文本console.log(box.innerText);// 考虑 CSS 样式隐藏元素返回空/script属性特点性能textContent获取所有文本不考虑 CSS更快innerText考虑 CSS 样式如display: none较慢推荐使用textContent除非你需要考虑 CSS 样式。四、操作元素属性4.1 标准属性对于 HTML 标准属性如id、className、href、src可以直接访问constlinkdocument.querySelector(a);// 读取console.log(link.href);console.log(link.id);// 设置link.hrefhttps://example.com;link.idnewId;// 特殊class 要用 className因为 class 是 JS 保留字element.classNameactive;4.2 自定义属性HTML5 允许使用data-*自定义属性dividboxdata-user-id123data-roleadmin/divscriptconstboxdocument.getElementById(box);// 读取console.log(box.dataset.userId);// 123自动转为驼峰console.log(box.dataset.role);// admin// 设置box.dataset.userId456;/script也可以使用通用方法// 任意属性都可用element.getAttribute(data-user-id);element.setAttribute(data-user-id,789);element.removeAttribute(data-user-id);五、操作元素样式5.1 style 属性直接修改内联样式constboxdocument.getElementById(box);box.style.width100px;box.style.height50px;box.style.backgroundColorred;// 注意用驼峰命名box.style.displaynone;缺点只能设置内联样式无法操作 CSS 类样式名需要转为驼峰background-color→backgroundColor5.2 classList推荐通过操作 CSS 类来控制样式style.active{background-color:red;}.hidden{display:none;}/styledividboxHello/divscriptconstboxdocument.getElementById(box);// 添加类box.classList.add(active);// 移除类box.classList.remove(active);// 切换类有则移除无则添加box.classList.toggle(hidden);// 判断是否包含类if(box.classList.contains(active)){console.log(box 是激活状态);}/script方法作用add()添加类remove()移除类toggle()切换类contains()判断是否包含replace(old, new)替换类推荐使用classList样式与行为分离易于维护。六、动态创建与删除元素6.1 创建元素// 创建元素constdivdocument.createElement(div);// 设置属性和内容div.idnewDiv;div.classNamebox;div.textContent新创建的元素;// 或使用 innerHTMLdiv.innerHTMLspan内容/span;6.2 添加元素dividcontainerpidfirst第一段/p/divscriptconstcontainerdocument.getElementById(container);constnewDivdocument.createElement(div);newDiv.textContent新元素;// 追加到末尾container.appendChild(newDiv);// 插入到指定元素之前constfirstdocument.getElementById(first);container.insertBefore(newDiv,first);// 新方法更直观container.append(newDiv);// 末尾添加container.prepend(newDiv);// 开头添加first.before(newDiv);// 在 first 之前插入first.after(newDiv);// 在 first 之后插入/script6.3 删除元素constboxdocument.getElementById(box);// 传统方法box.parentNode.removeChild(box);// 新方法推荐box.remove();七、事件处理7.1 事件绑定方式方式一HTML 属性不推荐buttononclickalert(点击了)点击/button缺点HTML 与 JS 混在一起难以维护。方式二DOM 属性constbtndocument.getElementById(btn);btn.onclickfunction(){alert(点击了);};// 缺点只能绑定一个处理函数后绑定的会覆盖前面的方式三addEventListener推荐constbtndocument.getElementById(btn);btn.addEventListener(click,function(){alert(点击了);});// 优点可以绑定多个处理函数btn.addEventListener(click,function(){console.log(另一个处理函数);});// 移除事件需要保持同一个函数引用functionhandleClick(){console.log(点击);}btn.addEventListener(click,handleClick);btn.removeEventListener(click,handleClick);7.2 常用事件事件触发时机click点击dblclick双击mouseenter鼠标进入mouseleave鼠标离开keydown键盘按下keyup键盘抬起focus获得焦点blur失去焦点input输入内容变化实时change值改变并失焦submit表单提交load资源加载完成DOMContentLoadedDOM 解析完成示例// 输入框实时响应constinputdocument.querySelector(input);input.addEventListener(input,function(){console.log(当前值,this.value);});// 表单提交constformdocument.querySelector(form);form.addEventListener(submit,function(e){e.preventDefault();// 阻止默认提交行为console.log(表单数据,newFormData(this));});7.3 事件对象事件处理函数会收到一个事件对象btn.addEventListener(click,function(e){console.log(e.target);// 触发事件的元素实际点击的console.log(e.currentTarget);// 绑定事件的元素this 指向它console.log(e.type);// 事件类型console.log(e.clientX,e.clientY);// 鼠标坐标e.preventDefault();// 阻止默认行为e.stopPropagation();// 阻止冒泡});target vs currentTargetulidlistli项目1/lili项目2/li/ulscriptconstlistdocument.getElementById(list);list.addEventListener(click,function(e){console.log(e.target);// 实际点击的 liconsole.log(e.currentTarget);// ul});/script7.4 事件委托问题动态添加的元素没有事件绑定// 只对已有的 li 生效新添加的没有事件document.querySelectorAll(li).forEach(li{li.addEventListener(click,function(){console.log(this.textContent);});});解决事件委托——将事件绑定到父元素利用冒泡机制constlistdocument.getElementById(list);list.addEventListener(click,function(e){// 判断点击的是否是 liif(e.target.tagNameLI){console.log(e.target.textContent);}});优点动态元素也有事件代码更简洁内存占用更少八、总结类别内容推荐方法获取元素选择元素querySelector/querySelectorAll操作内容读写文本/HTMLtextContent/innerHTML注意安全操作属性标准属性/自定义属性直接访问 /dataset操作样式控制样式classList创建元素动态生成元素createElementappend删除元素移除元素remove()事件绑定响应用户操作addEventListener事件优化动态元素事件事件委托核心记忆点用选择器方法获取元素用classList操作样式用addEventListener绑定事件动态元素用事件委托本文是前端三基石系列第二篇的续篇。下一篇将讲解异步编程与网络请求。

相关新闻

RedisInsight终极指南:如何快速掌握Redis可视化管理工具

RedisInsight终极指南:如何快速掌握Redis可视化管理工具

RedisInsight终极指南:如何快速掌握Redis可视化管理工具 【免费下载链接】RedisInsight Redis GUI by Redis 项目地址: https://gitcode.com/GitHub_Trending/re/RedisInsight RedisInsight是Redis官方推出的现代化GUI管理工具,它彻底改变了开发者…

2026/7/20 19:20:04阅读更多 →
Funchook错误处理与调试:常见错误代码解析和解决方案

Funchook错误处理与调试:常见错误代码解析和解决方案

Funchook错误处理与调试:常见错误代码解析和解决方案 【免费下载链接】funchook Hook function calls by inserting jump instructions at runtime 项目地址: https://gitcode.com/gh_mirrors/fu/funchook Funchook是一款强大的运行时函数钩子库,…

2026/7/20 19:20:04阅读更多 →
7 接雨水

7 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。示例 1:输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示…

2026/7/20 19:18:03阅读更多 →
Windows 11高效工具精选:12款必备神器提升系统性能

Windows 11高效工具精选:12款必备神器提升系统性能

1. Windows 11必备工具全景概览作为一位长期深耕Windows系统优化的技术博主,我深知新系统上手时的各种痛点。Windows 11虽然带来了现代化的界面设计,但很多细节设置反而比Windows 10更加隐蔽,系统自带的功能也常常无法满足高效办公的需求。经…

2026/7/21 10:41:58阅读更多 →
Qwen3.6-27B模型在5060Ti与V100显卡上的性能对比与优化

Qwen3.6-27B模型在5060Ti与V100显卡上的性能对比与优化

1. 项目概述 在本地大模型推理领域,显卡性能与模型量化技术的搭配选择一直是开发者关注的焦点。最近我针对Qwen3.6-27B模型的Q4量化版本,在5060Ti 16G和V100 32G两张显卡上进行了详细的对比测试。这两张显卡分别代表了不同世代的消费级和专业级产品&…

2026/7/21 10:41:58阅读更多 →
如何用Win11Debloat彻底清理Windows系统:150+预装应用一键移除指南

如何用Win11Debloat彻底清理Windows系统:150+预装应用一键移除指南

如何用Win11Debloat彻底清理Windows系统:150预装应用一键移除指南 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declu…

2026/7/21 10:41:58阅读更多 →
Nginx启用Brotli压缩算法实战指南

Nginx启用Brotli压缩算法实战指南

1. 为什么需要升级压缩算法?在Web性能优化中,资源压缩一直是关键环节。传统的gzip压缩虽然能有效减小传输体积,但随着现代Web应用复杂度提升,资源体积越来越大,我们需要更高效的压缩方案。Brotli是Google开发的新型压缩…

2026/7/21 10:41:58阅读更多 →
ExeinfoPe:Windows PE文件逆向工程与安全分析的瑞士军刀

ExeinfoPe:Windows PE文件逆向工程与安全分析的瑞士军刀

1. 项目概述:为什么我们需要ExeinfoPe?在逆向工程、恶意软件分析或者仅仅是好奇一个可执行文件“肚子里有什么货”的时候,我们遇到的第一个障碍往往不是复杂的算法,而是文件本身。一个.exe文件摆在你面前,它是什么编译…

2026/7/21 10:41:56阅读更多 →
深入解析TI CPSW架构:硬件时间同步与嵌入式网络性能优化

深入解析TI CPSW架构:硬件时间同步与嵌入式网络性能优化

1. CPSW架构概览与核心价值在嵌入式网络开发领域,尤其是工业自动化、汽车电子和电力系统这些对实时性和确定性要求极高的场景,网络通信的“快”和“准”是同等重要的。我们常常需要多个设备在微秒甚至纳秒级别上协调动作,比如机器人关节的同步…

2026/7/21 10:39:55阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 0:51:49阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 0:51:49阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 0:51:49阅读更多 →
Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

📌教程适配:OpenClaw v2.7.9 | 兼容 Windows10/11、macOS 双系统 📖前言 当下各类本地 AI 工具层出不穷,多数产品仅能完成文字问答交互,很难直接操控电脑执行实际操作。OpenClaw,业内常称小龙虾 AI&#…

2026/7/21 0:01:46阅读更多 →
Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

聊《一次Codex项目复盘,问题最后出在流程而不是模型》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要先把这篇文章的目标说清楚:看完之后,你应该能判断这件事值不值得做&…

2026/7/21 0:01:46阅读更多 →
手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

大家好,还是我。前几期带大家做了心情日记本和可视化大屏,后台有朋友留言:“能不能教点好玩的?我想做游戏,但一行代码都不会。”行,这期就安排。今天的目标:从零做一个五子棋游戏。 带AI对战、三…

2026/7/21 0:03:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/20 22:51:39阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/20 18:51:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/20 18:51:18阅读更多 →