你的位置:首页 > Java教程

[Java教程]JavaScript 详说事件机制之冒泡、捕获、传播、委托


DOM事件流(event  flow )存在三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。

事件捕获(dubbed  bubbling)通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。

事件冒泡(event  capturing)与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点。

无论是事件捕获还是事件冒泡,它们都有一个共同的行为,就是事件传播,它就像一跟引线,只有通过引线才能将绑在引线上的鞭炮(事件监听器)引爆,试想一下,如果引线不导火了,那鞭炮就只有一响了!!!

  

  dom标准事件流的触发的先后顺序为:先捕获再冒泡,即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。不同的浏览器对此有着不同的实现,IE10及以下不支持捕获型事件,所以就少了一个事件捕获阶段,IE11、Chrome 、Firefox、Safari等浏览器则同时存在。

说到事件冒泡与捕获就不得不提一下两个用于事件绑定的方法addEventListener、attachEvent。当然还有其它的事件绑定的方式这里不做介绍。 

  addEventListener(event, listener, useCapture)  

    ·参数定义:event---(事件名称,如click,不带on),listener---事件监听函数,useCapture---是否采用事件捕获进行事件捕捉,

        默认为false,即采用事件冒泡方式

    addEventListener在 IE11、Chrome 、Firefox、Safari等浏览器都得到支持。

  attachEvent(event,listener)  

    ·参数定义:event---(事件名称,如onclick,带on),listener---事件监听函数。

    attachEvent主要用于IE浏览器,并且仅在IE10及以下才支持,IE11已经废了这个方法了(微软还是挺识趣的,慢慢向标准靠拢)。

 

说了一箩筐定义,下面就用上面这两个方法通过栗子来解释一下事件捕获与事件冒泡的具体表现行为差异。

事件冒泡

栗1:

<html lang="zh-cn"><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  <title>js事件机制</title>  <style>    #parent{      width: 200px;      height:200px;      text-align: center;      line-height: 3;      background: green;    }    #child{      width: 100px;      height: 100px;      margin: 0 auto;      background: orange;    }  </style>  </head><body>  <div id="parent">    父元素    <div id="child">      子元素    </div>  </div>  <script type="text/javascript">    var parent = document.getElementById("parent");    var child = document.getElementById("child");      document.body.addEventListener("click",function(e){      console.log("click-body");    },false);        parent.addEventListener("click",function(e){      console.log("click-parent");    },false);    child.addEventListener("click",function(e){      console.log("click-child");    },false);  </script></body></html>

通过"addEventListener"方法,采用事件冒泡方式给dom元素注册click事件,点击子元素会发生什么呢?如果你对事件冒泡有一定了解的话那你肯定知道上面的代码会输出的顺序,没错,如下图所示:

事件触发顺序是由内到外的,这就是事件冒泡,虽然只点击子元素,但是它的父元素也会触发相应的事件,其实这是合理的,因为子元素在父元素里面,点击子元素也就相当于变相的点击了父元素,这样理解对吧?

这里有同学可能要问了,如果点击子元素不想触发父元素的事件怎么办?肯定可以的,那就是停止事件传播---event.stopPropagation();

修改栗1的代码,在子元素的监听函数中加入停止事件传播的操作,栗2

child.addEventListener("click",function(e){  console.log("click-child");  e.stopPropagation();},false);

在点击子元素的时候就只弹出了子元素那条信息,父元素的事件没有触发,因为事件已经停止传播了,冒泡阶段也就停止了。

事件冒泡差不多就讲述完了,别急,捕获还没说呢!

事件捕获

栗3,修改栗子1中的代码,给parent元素注册一个捕获事件,如下

     var parent = document.getElementById("parent");    var child = document.getElementById("child");      document.body.addEventListener("click",function(e){      console.log("click-body");    },false);        parent.addEventListener("click",function(e){      console.log("click-parent---事件传播");    },false);     
     //新增事件捕获事件代码 parent.addEventListener("click",function(e){ console.log("click-parent--事件捕获"); },true); child.addEventListener("click",function(e){ console.log("click-child"); },false);

如果你看明白了我前面说的那些,你就知道这个栗子的输出顺序了。

父元素通过事件捕获的方式注册了click事件,所以在事件捕获阶段就会触发,然后到了目标阶段,即事件源,之后进行事件传播,parent同时也用冒泡方式注册了click事件,所以这里会触发冒泡事件,最后到根节点。这就是整个事件流程。

 

上面介绍了事件冒泡、事件捕获、事件传播,下面讲一下如果通过以上三个知识点进行事件委托

 

委托在JQuery中已经得到了实现,即通过$(selector).on(event,childSelector,data,function,map)实现委托,一般用于动态生成的元素,当然JQuery也是通过原声的js去实现的,下面举一个简单的栗子,通过js实现通过parent元素给child元素注册click事件

var parent = document.getElementById("parent");var child = document.getElementById("child");parent.onclick = function(e){      if(e.target.id == "child"){        console.log("您点击了child元素")      }}

虽然没有直接只child元素注册click事件,可是点击child元素时却弹出了提示信息。

到这里你是不是有js的事件机制有一定的了解了呢?感觉有帮助的话就看看下面的小黄脸,你懂得哦!

如有错误,欢迎指正

如有问题,欢迎提问

 




内蒙古旅游报价价格内蒙古旅游团报价什么时候去内蒙古旅游最好去内蒙古旅游最佳路线内蒙古旅游景点推荐不能承受之重:全球十大恐怖巨坑(全文) 民俗野趣两相宜 我在高粱地里等你 百里百村百景 古香古色定安之旅 深圳麦鲁小城在哪里?麦鲁小城地址? 荷包岛码头船票价格?珠海荷包岛码头怎么去荷包岛? 珠海荷包岛船票预订电话?荷包岛船票网上可以预订吗? 荷包岛最后一班船票几点?珠海荷包岛船票往返的吗? 到珠海荷包岛船票多少钱?荷包岛船票预订? 牯牛降漂流价格?安徽牯牛降漂流开漂时间? 腾格里天鹅湖什么时间能看到天鹅?腾格里沙漠天鹅湖赏天鹅最佳时间? 趵突泉5月有什么好玩的?济南趵突泉几月去合适? 腾格里天鹅湖景区有篝火晚会吗?腾格里沙漠天鹅湖景区篝火晚会几点开始? 北京有哪些有名的、安全的夜店?去夜店有什么注意事项? 北京哪些地方容易堵车?什么时候堵车概率大? 厦门冬天穿什么?可以穿裙子吗? 北京的公交是怎么收费的?坐公交需不需要办张交通卡? 554-3121-411 Datasheet 554-3121-411 Datasheet 554-3121-511 Datasheet 554-3121-511 Datasheet 554-3122 Datasheet 554-3122 Datasheet 丽水去港澳游 丽水去港澳游 丽水去港澳游 通化去香港旅游 通化去香港旅游 通化去香港旅游 秦皇岛去港澳旅游 秦皇岛去港澳旅游 秦皇岛去港澳旅游