⚡ 编程实验室🏗️ HTML🎨 CSS⚡ JavaScript🐍 Python🗄️ SQL☕ Java⚛️ React💚 Vue🟢 Node.js⚙️ C语言🐘 PHP🐹 Go🔷 TypeScript🐬 MySQL🔧 C++🎯 C#🦀 Rust🅱️ Bootstrap💡 jQuery🎸 Django🍃 MongoDB👗 Sass🎪 Kotlin📊 R语言📋 XML📊 Excel🐘 PostgreSQL🐳 Docker🅰️ Angular🎮 游戏🏠 网站首页

JavaScript 事件处理

学习 click/input/keydown 等事件监听 · 难度:进阶 · +15XP

JavaScript 事件处理 — 让网页响应用户操作

一、什么是事件?为什么它如此重要?

事件(Event)是浏览器在用户操作(或系统触发)时发出的信号。当用户点击按钮、按下键盘、移动鼠标、滚动页面、提交表单时,浏览器都会生成对应的事件对象。JavaScript 通过事件监听器(Event Listener)来捕获这些信号并执行相应代码。

为什么事件处理重要?没有事件,网页就失去了交互性。用户点击按钮没有反应,输入表单没有验证,页面就和一个静态 PDF 没有区别。事件处理是前端开发的核心技能,掌握它意味着你可以创建任何你想要的交互体验。

事件处理涉及三个核心概念:

二、事件绑定的三种方式 — 全面对比

方式语法优点缺点
HTML 属性<button onclick="handle()">简单直观耦合 HTML/JS,不便维护
DOM 属性btn.onclick = handle;JS 中直接赋值只能绑定一个处理器
addEventListenerbtn.addEventListener("click", handle);可绑定多个、可移除、支持选项语法稍长(推荐!)

三、常用事件类型一览表

分类事件名触发时机常用场景
鼠标事件click鼠标单击按钮点击、链接点击
dblclick鼠标双击双击编辑
mouseover / mouseout鼠标移入/移出悬停提示、菜单展开
键盘事件keydown / keyup按键按下/松开快捷键、游戏控制
input输入框内容变化实时搜索、字数统计
表单事件submit表单提交表单验证、AJAX 提交
change选择或值改变下拉菜单、复选框
文档事件DOMContentLoadedHTML 解析完成初始化脚本
scroll页面滚动懒加载、回到顶部
触摸事件touchstart手指触摸屏幕移动端手势
touchend手指离开屏幕移动端点击

四、详细代码示例(逐行注释)

// ======== 1. addEventListener — 标准事件绑定 ========
const btn = document.querySelector("#my-btn");
// 参数1:事件类型,参数2:处理函数,参数3:选项(可选)
btn.addEventListener("click", function(event) {
  console.log("按钮被点击了!");
  console.log("事件对象:", event);      // event 包含事件的所有信息
  console.log("点击的目标元素:", event.target);
  console.log("鼠标坐标:", event.clientX, event.clientY);
});

// ======== 2. 事件对象(Event Object)常用属性 ======== document.addEventListener("click", function(e) { console.log(e.type); // 事件类型:"click" console.log(e.target); // 触发事件的元素 console.log(e.currentTarget); // 绑定事件的元素(事件委托时和 target 不同) console.log(e.clientX, e.clientY); // 鼠标相对视口的坐标 console.log(e.pageX, e.pageY); // 鼠标相对文档的坐标 // 键盘事件特有 // console.log(e.key); // 按下的键:"Enter"、"a"、"ArrowUp" // console.log(e.code); // 物理键位:"KeyA"、"Space" // console.log(e.ctrlKey); // 是否同时按了 Ctrl });

// ======== 3. 移除事件监听 ======== function handleClick() { console.log("只执行一次"); btn.removeEventListener("click", handleClick); // 移除监听 } btn.addEventListener("click", handleClick);

// ======== 4. 事件委托(Event Delegation)— 性能优化关键 ======== // 不要在 1000 个 li 上分别绑定事件!而是绑定在父元素上 const list = document.querySelector("#my-list"); list.addEventListener("click", function(e) { // 判断点击的是否是 li 元素 if (e.target.tagName === "LI") { console.log("你点击了:", e.target.textContent); e.target.classList.toggle("selected"); // 切换选中状态 } // 更健壮的判断方式(匹配特定选择器) if (e.target.matches(".delete-btn")) { // 点击了删除按钮 e.target.closest("li").remove(); // 删除最近的 li 祖先 } }); // 好处:后续动态添加的 li 也能自动响应点击,无需重新绑定!

// ======== 5. 阻止默认行为 + 阻止冒泡 ======== const form = document.querySelector("form"); form.addEventListener("submit", function(e) { e.preventDefault(); // 阻止表单的默认提交行为(页面刷新) // 改为 AJAX 提交 const formData = new FormData(form); console.log("用 AJAX 提交数据,页面不刷新"); // fetch("/api/submit", { method: "POST", body: formData }); });

const inner = document.querySelector(".inner"); inner.addEventListener("click", function(e) { e.stopPropagation(); // 阻止事件冒泡(父元素不会收到这个点击事件) console.log("只触发 inner,不触发 outer"); });

// ======== 6. 事件传播三阶段 ======== // 捕获阶段(Capture)→ 目标阶段(Target)→ 冒泡阶段(Bubble) const outer = document.querySelector(".outer"); outer.addEventListener("click", function() { console.log("冒泡阶段触发(默认)"); }); outer.addEventListener("click", function() { console.log("捕获阶段触发"); }, true); // 第三个参数 true = 捕获阶段监听

// ======== 7. 键盘事件 — 实现快捷键 ======== document.addEventListener("keydown", function(e) { // Ctrl + S 保存快捷键 if (e.ctrlKey && e.key === "s") { e.preventDefault(); // 阻止浏览器默认的保存网页行为 console.log("触发了自定义保存功能!"); } // Esc 关闭弹窗 if (e.key === "Escape") { document.querySelector(".modal").style.display = "none"; } });

// ======== 8. 防抖(Debounce)— 减少高频事件触发 ======== // 搜索框输入时,等用户停止输入 500ms 后才发送请求 function debounce(fn, delay) { let timer = null; // 闭包保存定时器 ID return function(...args) { // 返回新函数 clearTimeout(timer); // 清除上一次的定时器 timer = setTimeout(() => { // 设置新的定时器 fn.apply(this, args); // delay 毫秒后执行 }, delay); }; } const searchInput = document.querySelector("#search"); searchInput.addEventListener("input", debounce(function(e) { console.log("发送搜索请求:", e.target.value); // 实际项目中这里会调用 API 搜索 }, 500));

// ======== 9. 节流(Throttle)— 限制执行频率 ======== // 滚动事件每 200ms 最多触发一次 function throttle(fn, interval) { let lastTime = 0; // 上次执行时间 return function(...args) { const now = Date.now(); // 当前时间 if (now - lastTime >= interval) { // 超过间隔才执行 lastTime = now; fn.apply(this, args); } }; } window.addEventListener("scroll", throttle(function() { console.log("滚动位置:", window.scrollY); }, 200));

// ======== 10. once 选项 — 一次性事件 ======== btn.addEventListener("click", function() { console.log("这个按钮点击一次后自动解绑"); }, { once: true }); // once 选项,触发一次后自动移除

五、事件冒泡 vs 捕获 — 一张图看懂

阶段方向顺序addEventListener 第三个参数
捕获阶段从外向内 ↓window → document → html → body → ... → 目标元素true 或 {capture: true}
目标阶段到达目标元素本身顺序按绑定先后
冒泡阶段从内向外 ↑目标元素 → ... → body → html → document → windowfalse(默认)

六、实践任务

  1. 创建一个按钮,使用 addEventListener 绑定点击事件,每次点击计数器 +1 并显示在页面上
  2. 创建一个输入框,使用防抖(debounce)实现:用户停止输入 1 秒后,在下方显示"搜索:xxx"
  3. 创建一个 <ul> 列表,使用事件委托实现:点击任意 <li> 高亮显示,点击删除按钮删除该项
  4. 实现 Ctrl+Enter 快捷键提交表单
  5. 实现一个模态弹窗:点击"打开"显示弹窗,点击遮罩层(背景)或按 Esc 键关闭弹窗
Ctrl+Enter
🚀 升级VIP
解锁全部课程+AI助手

🏆 学习排行

加载中...

📊 统计

📖 231 篇
0 完成
🔥 0