找回密码
 立即注册
首页 业界区 业界 Web前端入门第 74 问:JavaScript 事件冒泡与事件捕获 ...

Web前端入门第 74 问:JavaScript 事件冒泡与事件捕获

广性 2025-9-25 21:05:50
在讨论冒泡和捕获之前,先看这么一段代码:
  1.   外层
  2.   
  3.     内层
  4.    
  5.       最内层
  6.       
  7.         按钮
  8.       
  9.    
  10.   
复制代码
页面渲染大概长这样:
1.png

点击最里面的 按钮 元素,按照思维惯例,是否应该先执行 container1 的点击事件??毕竟 container1 是最外层,而且也是最先绑定事件的元素。
然而控制台输出结果为:
  1. container4
  2. container3
  3. container2
  4. container1
复制代码
有点出乎意料是吧,为什么先执行的是 container4 呢?
事件冒泡

JS 绑定的事件默认是冒泡规则,什么意思呢?可以理解为:触发事件后就像水里面有一个泡泡,在水底慢慢的往上冒,从触发事件的目标元素开始,经过一层一层的盒模型,分别触发盒模型身上绑定的事件。
所以上面代码中,在点击 按钮 时,先触发了本身绑定的 click 事件,再一层一层往外传播,最终就打印出了控制台输出的结果。
事件捕获

注意:仅默认状态下,事件是冒泡规则,在绑定事件时候,可以修改第三个配置参数改为由外向内传播,这种传播顺序就是 事件捕获 。
以上面代码为蓝本,仅添加 addEventListener 的第三个参数为 true,就将绑定规则改为了 事件捕获 。如下:
  1. container1.addEventListener('click', () => {
  2.   console.log('container1')
  3. }, true)
  4. container2.addEventListener('click', () => {
  5.   console.log('container2')
  6. }, true)
  7. container3.addEventListener('click', () => {
  8.   console.log('container3')
  9. }, true)
  10. container4.addEventListener('click', () => {
  11.   console.log('container4')
  12. }, true)
复制代码
还是点击 按钮,上面代码执行结果:
  1. container1
  2. container2
  3. container3
  4. container4
复制代码
事件捕获还有另一种写法,第三个参数可以传入一个对象,通过对象的 capture 属性设置为事件捕获。
  1. container1.addEventListener('click', () => {
  2.   console.log('container1')
  3. }, {
  4.   // 另一种设置事件捕获方式
  5.   capture: true,
  6. })
复制代码
冒泡与捕获顺序

既然同一个事件有冒泡与捕获,那么冒泡与捕获的顺序如何?上例子:
  1. container1.addEventListener('click', () => {
  2.   console.log('冒泡:', 'container1')
  3. })
  4. container2.addEventListener('click', () => {
  5.   console.log('冒泡:', 'container2')
  6. })
  7. container3.addEventListener('click', () => {
  8.   console.log('冒泡:', 'container3')
  9. })
  10. container4.addEventListener('click', () => {
  11.   console.log('冒泡:', 'container4')
  12. })
  13. container1.addEventListener('click', () => {
  14.   console.log('捕获:', 'container1')
  15. }, true)
  16. container2.addEventListener('click', () => {
  17.   console.log('捕获:', 'container2')
  18. }, true)
  19. container3.addEventListener('click', () => {
  20.   console.log('捕获:', 'container3')
  21. }, true)
  22. container4.addEventListener('click', () => {
  23.   console.log('捕获:', 'container4')
  24. }, true)
复制代码
同时给元素绑定两种事件,点击 按钮 执行结果:
  1. 捕获: container1
  2. 捕获: container2
  3. 捕获: container3
  4. 捕获: container4
  5. 冒泡: container4
  6. 冒泡: container3
  7. 冒泡: container2
  8. 冒泡: container1
复制代码
到这里已经可以得出结论:JS 的事件传播会经历三个阶段,由 事件捕获 开始,传递到 目标元素 之后,就改为 事件冒泡,冒泡阶段完了之后事件结束。
阻止事件传播

既然事件有传播,那程序就有办法阻止事件传播。所有事件执行时都有一个 event 对象,此对象中有方法可用于阻止事件传播。
示例:
  1. container1.addEventListener('click', () => {
  2.   console.log('冒泡:', 'container1')
  3. })
  4. container2.addEventListener('click', () => {
  5.   console.log('冒泡:', 'container2')
  6. })
  7. container3.addEventListener('click', () => {
  8.   console.log('冒泡:', 'container3')
  9. })
  10. container4.addEventListener('click', () => {
  11.   console.log('冒泡:', 'container4')
  12. })
  13. container1.addEventListener('click', (event) => {
  14.   event.stopPropagation()
  15.   console.log('捕获:', 'container1')
  16. }, true)
  17. container2.addEventListener('click', () => {
  18.   console.log('捕获:', 'container2')
  19. }, true)
  20. container3.addEventListener('click', () => {
  21.   console.log('捕获:', 'container3')
  22. }, true)
  23. container4.addEventListener('click', () => {
  24.   console.log('捕获:', 'container4')
  25. }, true)
复制代码
注意 event.stopPropagation() 这个方法,此方法是阻止事件传播的关键。
以上代码在 container1 这个元素上就阻止了事件传播,所以点击 按钮 之后,仅 container1 会执行,其他所有元素都不会再触发,结果:
  1. 捕获: container1
复制代码
调用 event.stopPropagation() 就是告诉 JS,事件到此为止,不再继续了。
event 对象其他常用方法和属性:
event.target:触发事件的原始元素。
event.currentTarget:当前绑定事件的元素(等同于 this)。
event.type:事件类型(如 "click")。
event.preventDefault():阻止默认行为(如表单提交、链接跳转、自定义右键菜单)。
event.stopPropagation():阻止事件冒泡。
event.stopImmediatePropagation():阻止同一元素的其他监听器执行。
event.x 和 event.y:鼠标点击位置的坐标。
在事件中要使用 this 获取元素时,必须使用 function 函数,使用箭头函数绑定的事件 this 将会指向外层作用域的 this 指针,如下代码中箭头函数 this 指向的是 Window :
  1.   按钮
复制代码
写在最后

编程中的细节问题,总是越挖掘越心惊,学得越来越多,才会发现知道的越来越少。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册