在js中存在事件冒泡与事件捕获两种概念,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题。

事件冒泡(dubbed bubbling)

事件冒泡我们从字面意思理解就是当用户行为触发我们页面的定义好的事件后,会有一个由内到外的一个冒泡过程,而不是一下子就命中事件绑定的元素

事件捕获(event capturing)

事件捕获与冒泡恰恰相反,当鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件

我们用代码来理解一下

在下边这个例子中,如果两个元素都有一个click的处理函数,那么我们怎么才能知道哪一个函数会首先被触发呢?为了解决这种脑壳痛的问题,就有了今天的主题冒泡与捕获

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JS事件处理程序</title>
<link href="https://cdn.bootcss.com/skeleton/2.0.4/skeleton.min.css" rel="stylesheet">
</head> <body>
<div class="wrapper" id="wrapper">
<div class="container">
<button id="event">JS事件处理程序</button>
</div>
</div> <script>
var wrapper = document.getElementById("wrapper"),
event = document.getElementById("event"); wrapper.addEventListener("click", function () {
alert("1");
console.log("1");
}, true)
event.addEventListener("click", function () {
alert("2");
console.log("2");
}, true)
wrapper.addEventListener("click", function () {
alert("3");
console.log("3");
}, false)
event.addEventListener("click", function () {
alert("4");
console.log("4");
}, false)
</script>
</body> </html>

上面的代码最终输出结果为:

  • 1

  • 2

  • 4

  • 3

在DOM2级事件规定的时间流包括 三个阶段:

  • 事件捕获阶段

  • 处于目标阶段

  • 事件冒泡阶段

我们可以看到addEventListener的第三个参数我们传入的不同,也就是上面结果为什么没有顺序执行的原因,这里我们在来回顾一下addEventListener

addEventListener

语法: target.addEventListener(type, listener[, useCapture])
useCapture 可选Boolean, 当useCapture为true 事件句柄在捕获阶段执行,也就是事件由外向内执行 当useCapture为false 事件句柄在冒泡阶段执行,也就是事件由内向外执行

看到这也应该了解上面代码为何会输出1243了

好了,回来业务中,实际应用场景我们肯定不愿同时触发多个click, 在点击子元素时我们不想触发父元素的事, 这个时候我们就可以使用stopPropagation来停止事件冒泡

代码理解

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JS事件处理程序</title>
<link href="https://cdn.bootcss.com/skeleton/2.0.4/skeleton.min.css" rel="stylesheet">
</head> <body>
<div class="wrapper" id="wrapper">
<div class="container">
<button id="event">JS事件处理程序</button>
</div>
</div> <script> var wrapper = document.getElementById("wrapper"),
event = document.getElementById("event"); wrapper.onclick = function () {
console.log('捕获阶段执行父元素wrapper的事件处理程序')
} event.onclick = function () {
// 阻止事件冒泡
e.stopPropagation()
console.log('冒泡阶段执行子元素event的事件处理程序')
} </script>
</body> </html>

上面的示例中我们使用了stopPropagation来阻止冒泡,所以此时只会触发一个事件了

总结

  • 事件冒泡由内向外执行

  • 事件传播由外向内执行

  • addEventListener的第三个参数可以改变事件流的状态

  • 使用stopPropagation可以阻止冒泡

JS事件冒泡与事件捕获怎么理解?的更多相关文章

  1. JS事件(事件冒泡和事件捕获)

    事件流:描述的是在页面中接收事件的顺序 事件冒泡:由最具体的元素接收,然后逐级向上传播至最不具体的元素的节点(文档) 事件捕获:最不具体的节点先接收事件,而最具体的节点应该是最后接收事件 DOM中:用 ...

  2. js 事件冒泡和事件捕获

    事件流:指的是网页中元素接受事件的顺序,它是一个概念,而不是具体的实际的东西 事件冒泡:指的是内层元素的事件,会触发包含着此元素的外层元素的事件,触发的顺序是:由内而外的 例如: <!DOCTY ...

  3. 彻底弄懂JS的事件冒泡和事件捕获(不推荐阅读)

    由于搬去敌台了,好久没来博客园,今天无意中翻到有“误认子弟”的评论,这里特意做个说明. 本文中关于事件冒泡和事件捕获的描述和例子都是OK的,错就错在后面用jquery去展示了利用事件冒泡的例子有误,其 ...

  4. js进阶 12-2 彻底弄懂JS的事件冒泡和事件捕获

    js进阶 12-2 彻底弄懂JS的事件冒泡和事件捕获 一.总结 一句话总结:他们是描述事件触发时序问题的术语.事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件.相反的,事件 ...

  5. 浅谈js的事件冒泡和事件捕获

    本文地址:https://www.cnblogs.com/christineqing/p/7607113.html 前言:    这篇文章起源于上次工作上的原因,在事件上出的bug,所以就抽空写出一篇 ...

  6. JS中的事件绑定,事件捕获,事件冒泡以及事件委托,兼容IE

    转载请注明出处:http://www.cnblogs.com/zhangmingze/p/4864367.html   ● 事件分为三个阶段:   事件捕获 -->  事件目标 -->   ...

  7. 彻底弄懂JS的事件冒泡和事件捕获

      先上结论:在事件执行流中有两种执行方式.一种是事件冒泡(即事件的执行顺序是从下往上执行的) ;  另一种是捕获(即事件的执行顺序是从上往下执行的); 阻止事件冒泡:   return false; ...

  8. js高级:event,事件冒泡,事件捕获

    1.事件 浏览器客户端上客户触发的行为都称为事件 所有的事件都是天生自带的,不需要我们去绑定,只需要我们去触发. 通过 obj.事件名=function(){} 事件名:onmouseover 鼠标悬 ...

  9. JS高级:事件冒泡和事件捕获;

    1.事件:浏览器客户端上客户触发的行为成为时事件:所有的事件都是天生自带的,不需要我们去绑定,只需要我们去触发 当用户触发一个事件时,浏览器的所有详细信息都存在一个叫做event的对象上,我们把它叫做 ...

随机推荐

  1. ABA 问题

    CAS 导致 ABA 问题CAS 算法实现了一个重要的前提,需要取出内存中某时刻的数据,并在当下时刻比较并替换,那么这个时间差会导致数据的变化. 比如说一个线程 one 从内存位置 V 中取出A,这时 ...

  2. SpringBoot-RestTemplate测试Controller

    1.功能测试类 package com.imooc.controller; import java.io.IOException; import java.math.BigDecimal; impor ...

  3. MyBatis Collection小记—— 关联查询、递归查询、多字段关联

    经常会用到mybatis的Collection标签来做级联查询或递归查询,现通过一个伪例来简单的说明一下使用中的关键点: 首先先列出三个表,给出一个场景: 1,角色表 t_role( id,name ...

  4. JavaIO——内存操作流、打印流

    我们之前所做的都是对文件进行IO处理,实则我们也可以对内存进行IO处理.我们将发生在内存中的IO处理称为内存流. 内存操作流也可分为两类:字节内存流和字符内存流. (1)ByteArrayInputS ...

  5. velocity示例

    创建maven项目 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns ...

  6. JS 的三种定义变量 var let const

    Let 只在 let 命令所在的代码块内有效,在外就会报错 Let 是块级作用域,函数内部使用let定义后,对函数外部无影响 Let/const 不存在变量提升,使用前一定要声明后,在使用,否则会报错 ...

  7. 【Java 8】Stream通过reduce()方法合并流为一条数据示例

    在本页中,我们将提供 Java 8 Stream reduce()示例. Stream reduce()对流的元素执行缩减.它使用恒等式和累加器函数进行归约. 在并行处理中,我们可以将合并器函数作为附 ...

  8. Jenkins构建通知

    目录 一.简介 二.推送到gitlab 三.邮件通知 自带配置 Email Extension 四.钉钉通知 五.脚本钉钉通知 六.HTTP请求通知 一.简介 类似于监控报警,jenkins在配置持续 ...

  9. ABP VNext框架基础知识介绍(2)--微服务的网关

    ABP VNext框架如果不考虑在微服务上的应用,也就是开发单体应用解决方案,虽然也是模块化开发,但其集成使用的难度会降低一个层级,不过ABP VNext和ABP框架一样,基础内容都会设计很多内容,如 ...

  10. 转:Memcached 线程部分源码分析

    目前网上关于memcached的分析主要是内存管理部分,下面对memcached的线程模型做下简单分析 有不对的地方还请大家指正,对memcahced和libevent不熟悉的请先google之 先看 ...