事件捕获和事件冒泡

事件冒泡

IE的事件流叫做事件冒泡。即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。所有现代浏览器都支持事件冒泡,并且会将事件一直冒泡到window对象
在这里插入图片描述

事件捕获

事件捕获的思想是不太具体的节点应该更早的接收到事件,而在最具体的节点应该最后接收到事件。事件捕获的用以在于事件到达预定目标之前捕获它。IE9+、Safari、Chrome、Opera和Firefox支持,且从window开始捕获(尽管DOM2级事件规范要求从document)。由于老版本浏览器不支持,所以很少有人使用事件捕获。
在这里插入图片描述

DOM事件流

“DOM2级事件”规定事件流包括三个阶段,事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的事件捕获,为截获事件提供了机会。然后是实际的目标接收了事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。
在这里插入图片描述

例子

<div id="a">
    <div id="b">
        <div id="c"></div>
    </div>
</div>
<script>
var a = document.getElementById("a"),
    b = document.getElementById("b"),
    c = document.getElementById("c");
c.addEventListener("click", function (event) {
    console.log("c1");
    // 注意第三个参数没有传进 false , 因为默认传进来的是 false
    //,代表冒泡阶段调用,个人认为处于目标阶段也会调用的
});
c.addEventListener("click", function (event) {
    console.log("c2");
}, true);
b.addEventListener("click", function (event) {
    console.log("b");
}, true);
a.addEventListener("click", function (event) {
    console.log("a1");
}, true);
a.addEventListener("click", function (event) {
    console.log("a2")
});
a.addEventListener("click", function (event) {
    console.log("a3");
    event.stopImmediatePropagation();
}, true);
a.addEventListener("click", function (event) {
    console.log("a4");
}, true);
</script>

在这里插入图片描述

  1. addEventListener函数参数说明
    element.addEventListener(event, function, useCapture)
  • 第一个参数是需要绑定的事件
  • 第二个参数是触发事件后要执行的函数
  • 第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。
  1. event.stopImmediatePropagation()
    作用:阻止事件冒泡并且阻止相同事件的其他侦听器被调用。
  2. event.stopPropagation 停止事件冒泡
  3. event.preventDefault 取消事件(如果该事件可取消)

  1. 判断以下
  • 如果点击c或者b,输出什么?(答案是a1、a3)
    stopImmediatePropagation包含了stopPropagation的功能,即阻止事件传播(捕获或冒泡),但同时也阻止该元素上后来绑定的事件处理程序被调用,所以不输出 a4。因为事件捕获被拦截了,自然不会触发 b、c 上的事件,所以不输出 b、c1、c2,冒泡更谈不上了,所以不输出 a2。

  • 如果点击a,输出什么?(答案是 a1、a2、a3)
    不应该是 a1、a3、a2 吗?有同学就会说:“a1、a3可是在捕获阶段被调用的处理程序的,a2 是在冒泡阶段被调用的啊。”这正是要说明的:虽然这三个事件处理程序注册时指定了true、false,但现在事件流是处于目标阶段,不是冒泡阶段、也不是捕获阶段,事件处理程序被调用的顺序是注册的顺序。不论你指定的是true还是false。换句话来说就是现在点击的是a这个盒子本身,它处于事件流的目标状态,而既非冒泡,又非捕获。(需要注意的是,此时的eventPhase为2,说明事件流处于目标阶段。当点击a的时候,先从document捕获,然后一步步往下找,找到a这个元素的时候,此时的target和currentTarget是一致的,所以认定到底了,不需要再捕获了,此时就按顺序执行已经预定的事件处理函数,执行完毕后再继续往上冒泡…)

  • 如果注释掉event.stopImmediatePropagation,点击c,会输出什么?(答案是 a1、a3、a4、b、c1、c2、a2)
    如果同一个事件处理程序(指针相同,比如用 handler 保存的事件处理程序),用 addEventListener或 attachEvent绑定多次,如果第三个参数是相同的话,也只会被调用一次。当然,如果第三个参数一个设置为true,另一个设置为false,那么会被调用两次。
    而在这里,都是给监听函数的回调赋予了一个匿名函数,所以其实每个处理函数都会被调用。需要注意的是,如果你还不明白为什么在c上触发的先是c1再是c2的话,那么你就需要在去看看第二个问题所描述的内容了(处于目标阶段会按照事件的绑定顺序来执行)

借鉴博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值