前言
前面我们已经学会了基础事件绑定、点击事件、页面滚动事件,也实现了博客的菜单切换、导航栏变色等交互。
但你有没有遇到过这些诡异问题:
给新增的列表项绑定点击事件,死活不生效?
点击一个按钮,触发了多次事件?
点击子元素,父元素的事件也跟着触发,代码乱执行?
这些问题,99% 都是因为不懂事件冒泡、事件捕获、事件委托。
本篇带你吃透 JS 事件底层机制,从根源解决新手交互BUG,学会企业级常用的事件委托写法,让你的代码更高效、更稳定、支持动态元素绑定事件。
一、先搞懂:JS事件执行的三个阶段
任何一次页面点击,都会经历三个阶段:
捕获阶段:从最外层祖先 → 往内层层查找元素
目标阶段:触发你真正点击的元素
冒泡阶段:从当前元素 → 向外层层触发父级事件
我们平时写的addEventListener,默认都是冒泡阶段触发。
二、重点核心:什么是事件冒泡?(新手最大坑)
事件冒泡:子元素触发事件后,会自动向上冒泡,触发所有父级同名事件。
举个直观例子:
卡片包含标题,你点击标题,不仅标题点击事件执行,卡片的点击事件也会执行,这就是冒泡。
冒泡实战演示
<div class="box"> <p class="text">点击我测试冒泡</p> </div> <script> document.querySelector(".box").onclick = function(){ console.log("父盒子被点击"); } document.querySelector(".text").onclick = function(){ console.log("文本被点击"); } </script>
你点击文字,控制台输出:
文本被点击 父盒子被点击
这就是冒泡导致的事件连锁触发,很多诡异BUG都是它造成的。
三、如何阻止冒泡?彻底解决事件混乱
只需要一行代码:event.stopPropagation()
document.querySelector(".text").onclick = function(e){ console.log("文本被点击"); // 阻止事件向上冒泡 e.stopPropagation(); }
加完之后,点击文本只会触发自身事件,不会触发父级事件。
所有多层嵌套点击交互,一定要学会阻止冒泡!
四、终极神器:事件委托(企业开发必用)
1. 新手痛点
之前我们循环渲染文章列表,动态新增的元素无法绑定事件,因为:
事件绑定在页面加载时完成
后渲染出来的元素,没有绑定过事件
如果循环给每一个列表项绑定事件,性能极低、代码冗余、新增元素失效。
2. 事件委托原理
利用事件冒泡:把所有子元素的事件,统一交给父元素处理。
只给父元素绑定一次事件,所有子元素(包括未来动态新增的子元素)全部生效。
3. 实战:给博客文章卡片添加点击跳转
我们不再给每一张文章卡片绑定点击事件,直接委托给父容器。
// 文章列表父容器委托事件 document.querySelector(".article-list").addEventListener("click",function(e){ // 判断点击的是不是文章卡片 if(e.target.closest(".article-card")){ alert("你点击了文章卡片,准备跳转阅读全文"); } })
事件委托的三大无敌优势
性能极高:不管10条、100条数据,只绑定一次事件
支持动态元素:JS后续新增的列表项,自动拥有点击事件
代码极简:无需循环绑定、无需重复操作
五、阻止默认事件
网页很多标签自带默认行为:
a标签默认跳转
表单提交默认刷新页面
右键默认弹出菜单
想要禁止默认行为,使用:e.preventDefault()
// 禁止a标签默认跳转 document.querySelector("a").addEventListener("click",function(e){ e.preventDefault(); console.log("跳转被拦截,执行自定义逻辑"); })
六、本篇新手必记总结
事件冒泡:子触发、父自动触发,是BUG来源,也是委托的基础
stopPropagation()阻止冒泡
preventDefault()阻止默认行为
事件委托:父级统一托管子元素事件,动态元素首选方案
所有列表类点击,优先使用事件委托,不要循环绑定
结语
学到这里,你的 JS 交互能力已经从“新手乱写”升级为规范、高效、底层通透。
普通新手只会绑定事件,你已经能掌控事件机制、解决疑难BUG、写出企业级代码。
下一篇,我们学习前端最常用的定时器 + 自动轮播实战,真正实现动态自动播放效果,完成博客进阶特效。