作者:夏天训练营
标签:JavaScript 事件流 事件冒泡 事件捕获 addEventListener 前端基础
🌈 前言
在前端开发中,事件是用户与页面交互的核心。但你是否曾被“事件流”、“冒泡”、“捕获”、“stopPropagation”这些概念绕晕?
别担心!本文将用生活化比喻 + 代码实例,带你从零彻底搞懂 JavaScript 事件流机制,让你不再“似懂非懂”。
1️⃣ 什么是事件流?
事件流(Event Flow)描述的是:当一个事件(如点击)发生时,它在 DOM 树中传播的完整路径。
它分为三个阶段:
| 阶段 | 说明 |
|---|---|
| 捕获阶段(Capture Phase) | 事件从 window → document → <html> → <body> → 一路“冲进”目标元素(从外到内) |
| 目标阶段(Target Phase) | 事件到达真正被点击的元素 |
| 冒泡阶段(Bubbling Phase) | 事件从目标元素“弹出”,一路返回到 window(从内到外) |
✅ 完整流程:捕获 → 目标 → 冒泡
2️⃣ 捕获 vs 冒泡:快递员的故事 📦
想象你住在一个三层复式公寓:
- 1楼:大门(最外层)
- 2楼:客厅
- 3楼:你的房间(最里层)
🚪 捕获阶段:快递员从外往里找你
快递员先敲大门 → 客厅 → 房间
→ 事件从外向内传播
🗣️ 冒泡阶段:你喊“谢谢”传出去
你收到包裹,喊“谢谢” → 声音传到客厅 → 大门
→ 事件从内向外传播
3️⃣ 默认监听的是“冒泡阶段”
btn.addEventListener('click', () => {
console.log('我被点击了!');
});
- ✅ 默认只在冒泡阶段执行
- ❌ 不会在捕获阶段执行
如何监听捕获阶段?
btn.addEventListener('click', fn, true); // 第三个参数为 true
4️⃣ 事件委托:用父元素监听子元素
<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
<li class="special">Item 3(特殊)</li>
</ul>
list.addEventListener('click', (e) => {
// e.target 是真正被点击的 li
if (e.target.classList.contains('special')) {
alert('你点了第3个 li!');
}
});
✅ 优点:无需给每个 li 绑定事件,性能更好,动态元素也适用。
5️⃣ stopPropagation vs stopImmediatePropagation
| 方法 | 作用 |
|---|---|
e.stopPropagation() | ❌ 阻止事件冒泡到父元素 ✅ 但同一元素的其他监听器仍会执行 |
e.stopImmediatePropagation() | ❌ 阻止冒泡 ❌ 且阻止当前元素后续所有监听器执行 |
el.addEventListener('click', e => {
e.stopImmediatePropagation(); // 全给我闭嘴!
});
6️⃣ 事件监听器 vs 事件:别再混淆!
| 概念 | 说明 |
|---|---|
| 事件(Event) | 用户行为,如点击、输入(浏览器自动创建) |
| 事件监听器(Listener) | 一段代码,事件发生时执行(你写的函数) |
addEventListener | 方法,用来“注册”监听器 |
btn.addEventListener('click', handleClick);
// ↑ ↑
// | └── 事件监听器
// └── 注册方法
7️⃣ 触发点击事件的 3 种方式
| 方式 | 说明 |
|---|---|
element.click() | 模拟用户点击,触发所有监听器 |
dispatchEvent() | 手动派发自定义事件 |
HTML onclick | 内联或 JS 赋值,不推荐 |
btn.click(); // 主动触发点击
8️⃣ 注意:不是所有事件都会冒泡!
| 事件 | 会冒泡吗? |
|---|---|
click | ✅ 是 |
input | ✅ 是 |
focus | ❌ 否 |
blur | ❌ 否 |
mouseenter | ❌ 否 |
⚠️
focus等事件不会冒泡,只能在目标元素或捕获阶段监听。
✅ 总结
- 事件流 = 捕获 → 目标 → 冒泡
- 默认监听冒泡阶段
- 用
e.target实现事件委托 stopPropagation阻止冒泡,stopImmediatePropagation彻底拦截addEventListener是注册方法,不是事件本身- 可用
click()或dispatchEvent()主动触发事件
🌟 结语
事件流是前端开发的基石,理解它,才能写出高效、可维护的交互逻辑。
希望本文能帮你彻底扫清疑惑,欢迎点赞、收藏、转发!
我是夏天训练营,一个热爱分享的前端学习者。
关注我,一起探索更多前端奥秘!🌿

被折叠的 条评论
为什么被折叠?



