一文教你掌握事件机制

JavaScript 的事件机制是前端交互的核心,它允许开发者监听用户行为(如点击、输入、滚动等)并作出响应。理解原生 JS 的事件模型对于写出高效、可维护的代码至关重要。

本文将从以下几个方面详细讲解 原生 JavaScript 的事件机制

一、什么是事件?

在浏览器中,事件(Event) 是当某些行为发生时由浏览器自动触发的通知。例如:

  • 用户点击按钮 → 触发 click 事件;
  • 鼠标移动到元素上 → 触发 mouseover 事件;
  • 表单提交 → 触发 submit 事件;

开发者可以通过编写"事件监听器"来响应这些事件。

二、绑定事件的方式

1. DOM 0 级事件处理(内联 / 属性式)

html 复制代码
<!-- HTML 内联 -->
<button onclick="sayHello()">点我</button>
js 复制代码
// JS 属性绑定
const btn = document.getElementById('btn');
btn.onclick = function() {
    alert('Hello');
};

⚠️ 缺点:

  • 只能绑定一个事件处理器;
  • 不利于代码分离;

2. DOM 2 级事件处理(推荐方式)

使用 addEventListener() 方法添加多个监听器,并支持捕获/冒泡阶段。

js 复制代码
btn.addEventListener('click', function(event) {
    console.log('按钮被点击了');
}, false);

参数说明:

参数 含义
'click' 事件类型(如 click、keydown、input 等)
function(event) 回调函数,接收事件对象
false 是否在捕获阶段执行,默认为 false(即冒泡阶段)

✅ 优点:

  • 支持多个监听器;
  • 支持捕获和冒泡;
  • 更加灵活、安全;

三、事件流的三个阶段

当你点击页面中的某个元素时,事件并不是直接触发一次,而是经历以下三个阶段:

1. 捕获阶段

事件从最外层 (如 windowdocument)向目标元素逐级传递。

css 复制代码
window → document → html → body → ... → target

在这个阶段,父级元素可以提前"感知"到事件即将到达目标。

2. 目标阶段

事件到达你真正点击的目标元素 。此时 event.target 被确定。

3. 冒泡阶段

事件从目标元素开始,向外层传播回根节点。

css 复制代码
target → ... → body → html → document → window

⚠️ 并非所有事件都会冒泡(如 focus, blur 就不会冒泡)。

四、useCapture 参数的作用

addEventListener() 的第三个参数控制监听器是在哪个阶段执行:

  • true:在捕获阶段执行;
  • false(默认):在冒泡阶段执行;
js 复制代码
document.getElementById('parent').addEventListener('click', () => {
    console.log('Parent');
}, true);

document.getElementById('child').addEventListener('click', () => {
    console.log('Child');
}, false);

点击 <div id="child"> 输出顺序:

复制代码
Parent 
Child 

五、事件对象(Event Object)

每个事件回调函数都会接收到一个事件对象(event),它包含了许多有用的信息:

js 复制代码
element.addEventListener('click', function(event) {
    console.log(event.type);        // 事件类型,如 'click'
    console.log(event.target);      // 触发事件的原始元素
    console.log(event.currentTarget); // 当前监听事件的元素(this)
    console.log(event.clientX, event.clientY); // 鼠标坐标
});

常用属性

属性 描述
type 事件类型
target 触发事件的真实元素
currentTarget 绑定监听器的元素(即 this
bubbles 该事件是否会冒泡
cancelable 是否可以阻止默认行为

六、阻止默认行为与事件传播

1. 阻止默认行为:preventDefault()

适用于链接跳转、表单提交等默认行为。

js 复制代码
form.addEventListener('submit', function(event) {
    event.preventDefault(); // 阻止表单提交
    console.log('表单未提交');
});

2. 阻止事件传播:stopPropagation()

阻止事件继续向上冒泡或向下捕获

js 复制代码
child.addEventListener('click', function(event) {
    event.stopPropagation();
    console.log('子元素被点击');
});

此时父元素的点击事件将不会被触发。


七、事件委托(Event Delegation)

由于事件会冒泡,我们可以将事件监听器放在父元素 上,统一处理子元素的事件,这就是事件委托

html 复制代码
<ul id="menu">
    <li>首页</li>
    <li>关于我们</li>
    <li>联系我们</li>
</ul>
js 复制代码
document.getElementById('menu').addEventListener('click', function(event) {
    if (event.target.tagName === 'LI') {
        console.log('你点击了:', event.target.innerText);
    }
});

✅ 优点:

  • 减少监听器数量
  • 动态添加的子元素也能响应事件
  • 提高性能

八、常见事件类型

事件类型 触发时机 事件类型 触发时机
click 鼠标点击或触屏点击 change input 元素失去焦点后内容改变
mousedown/mouseup 鼠标按下/释放 submit 表单提交
mousemove 鼠标移动 scroll 页面或元素滚动
keydown/keyup 键盘按键按下/释放 resize 窗口大小变化
input input 元素内容变化(实时) load 页面或资源加载完成
DOMContentLoaded HTML 文档解析完成但资源未加载完
相关推荐
像风一样自由20201 小时前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
aiprtem2 小时前
基于Flutter的web登录设计
前端·flutter
浪裡遊2 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
why技术2 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
GISer_Jing2 小时前
0704-0706上海,又聚上了
前端·新浪微博
止观止3 小时前
深入探索 pnpm:高效磁盘利用与灵活的包管理解决方案
前端·pnpm·前端工程化·包管理器
whale fall3 小时前
npm install安装的node_modules是什么
前端·npm·node.js
烛阴3 小时前
简单入门Python装饰器
前端·python
袁煦丞4 小时前
数据库设计神器DrawDB:cpolar内网穿透实验室第595个成功挑战
前端·程序员·远程工作
天天扭码4 小时前
从图片到语音:我是如何用两大模型API打造沉浸式英语学习工具的
前端·人工智能·github