【javaScript】addEventListener第三个参数的使用和事件冒泡和捕获机制

前言

续上一章 addEventListener()和attachEvent()跨浏览器的兼容性处理 将的addEventListener和attachEvent比较的第四个不同点续讲…

事件冒泡

概念:
当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window 。(注意这里传递的仅仅是事件 并不传递所绑定的事件函数。所以如果父级没有绑定事件函数,就算传递了事件 也不会有什么表现 但事件确实传递了。)
这就话怎么理解 >>> 看代码

var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
   div2.onclick = function(){alert(1);}; 
   div1.onclick = function(){};  //父亲

//html代码

 <div id="div1">
    <div id="div2"></div>
 </div>

这里我们要注意,我们传递的仅仅是事件触发,也就是说当点击div2仅仅触发了父级的点击事件,并没有把自己的绑定的函数给父级,父级的执行情况,取决于自己所绑定的函数,因为在这里它绑定的函数是空,自然没什么表现。有些人在这里有误解,所以强调一下

讲一下addEventListener第三个参数:

常用的语法格式
target.addEventListener(type, listener[, useCapture]);
type
表示监听事件类型的字符串 ---- 例如mousedown, click, submit等事件名
listener
当所监听的事件类型触发时,会接收到一个事件通知(实现了 Event 接口的对象)对象。listener 必须是一个实现了 EventListener 接口的对象,或者是一个函数 ---- 也就是函数fn()
useCapture
true:
事件句柄在捕获阶段执行 ---- 也就是事件捕获,事件传播方向为外向里
false:
默认;事件句柄在冒泡阶段执行 ---- 也就是事件捕获,事件传播方向为里向外

这里对addEventListener只是简单叙述,详情可看
MDN

代码展示(事件捕获的代码就不在展示啦,直接把false改为ture,输出结果就是 html body div):

<!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>Document</title>
</head>
<body >
<!--html-->
<div style="width: 400px;height: 400px;background: red" >
事件冒泡(点击这里)
</div>

<script>
   var div = document.querySelector("div");
   div.addEventListener("click",function (e) {
       alert("div")
   },false)

   var body = document.querySelector("body");
   body.addEventListener("click",function (e) {
       alert("body")
   },false)

   var html = document.querySelector("html");
   html.addEventListener("click",function (e) {
       alert("html")
   },false)
// 输出结果: div  body  html
</script>
</body>
</html>

图解:
冒泡机制

事件捕获

概念:
在事件捕获过程中, document 对象首先接收到 click 事件,然后事件沿 DOM 树依次向下,一直传播到事件的实际目标,是一种由外到内的传播
图解:
在这里插入图片描述
拓展:为什么要传播?
因为事件源本身(可能)并没有处理事件的能力,即处理事件的函数(方法)并未绑定在该事件源上。例如我们点击一个按钮时,就会产生一个click事件,但这个按钮本身可能不能处理这个事件,事件必须从这个按钮传播出去,从而到达能够处理这个事件的代码中(例如我们给按钮的onclick属性赋一个函数的名字,就是让这个函数去处理该按钮的click事件),或者按钮的父级绑定有事件函数,当该点击事件发生在按钮上,按钮本身并无处理事件函数,则传播到父级去处理。

来看一下一个经典的需求例子 引出stopPropagation和preventDefault

在这里插入图片描述
需求: 点击上面红色的面板让下面粉色的面板显示,点击其他地方再让粉丝面板隐藏;

代码:

<div id="div2" style="width: 100px;height: 100px;background: red;" >
点击2让下面的div显示,点击文档其他区域让他隐藏
</div>
<div id="div1" style="width: 100px;height: 100px;background: pink;display: none"></div>
var div2 = document.getElementById("div2");
var div1 = document.getElementById("div1");

 div2.onclick = function(){   //红色面板事件
    div1.style.display = "block"; 
  };
 document.onclick = function(){ 
    div1.style.display = "none"; 
 }

window中的on + type监听方法默认是【冒泡行为】

这个时候我们测试发现,怎么点击红色面板,粉丝面板都不会显示了,为什么呢?就是冒泡的原因,我们来分析下代码,当点击div2的时候,他会触发父亲级别的点击事件,然后一层一层的往上传,所以document的点击事件自然也被触发了,然后执行了自己身上的绑定事件,让粉色面板消失。所以当你点击div2的时候首先让粉色面板显示,只是事件执行太快了,很快又执行了document的点击事件,让面板隐藏。 有兴趣的可以再两个事件之间加一个弹出,这样就可以看到这个快速的过程啦

那么此时就可以通过组织事件冒泡解决上面的需求啦

取消事件冒泡有两种方式:

标准的W3C 方式:e.stopPropagation();这里的stopPropagation是标准的事件对象的一个方法,调用即可

非标准的IE方式:e.cancelBubble=true; 这里的cancelBubble是 IE事件对象的属性,设为true就是取阻止事件冒泡

同样(事件的默认行为):

标准的W3C 方式:e.preventDefault();这里的preventDefault是标准的事件对象的一个方法,调用即可

非标准的IE方式:e.returnValue=false; 这里的returnValue是 IE事件对象的属性,设为false就是取消事件的默认行为

通常我们会封装这样一个兼容性函数:

var preStop = {
        stopPropagation: function(e){
            var e = e || window.event;
            if(e.stopPropagation){
                e.stopPropagation
            }else{
                e.cancelBubble = true;
            }
        },
        preventDefault: function(e){
            var e = e || window.event;
            if(e.preventDefault){
                e.preventDefault();
            }else{
                e.returnValue = false;
            }
        } 
    }

那么上面的需求代码改成这样就可以啦 — 完成

var div2 = document.getElementById("div2");
var div1 = document.getElementById("div1");
var preStop = {
     stopPropagation: function(e){
          var e = e || window.event;
          if(e.stopPropagation){
              e.stopPropagation();
          }else{
              e.cancelBubble = true;
          }
      },
      preventDefault: function(e){
          var e = e || window.event;
          if(e.preventDefault){
              e.preventDefault();
          }else{
              e.returnValue = false;
      }
   } 
}
 div2.onclick = function(event){   //红色面板事件
    div1.style.display = "block";
    preStop.stopPropagation(event);
  };
 document.onclick = function(){ 
    div1.style.display = "none"; 
 }
完结

其实冒泡还有一大优点,就是事件委托,而且经常用到,还能提高很大的性能,想要了解可以看这个事件委托

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值