在线DEMO

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

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

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

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

  

  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的事件机制有一定的了解了呢?感觉有帮助的话就看看下面的小黄脸,你懂得哦!

如有错误,欢迎指正

如有问题,欢迎提问

作者:木法传

JavaScript 详说事件机制之冒泡、捕获、传播、委托的更多相关文章

  1. javascript 中的事件机制

    1.javascript中的事件. 事件流 javascript中的事件是以一种流的形式存在的. 一个事件会也有多个元素同时响应. 有时候这不是我们想要的效果, 我们只是需要某个特定的元素相应我们的绑 ...

  2. 【初窥javascript奥秘之事件机制】论“点透”与“鬼点击”

    前言 最近好好的研究了一番移动设备的点击响应速度,期间不断的被自己坑,最后搞得焦头烂额,就是现在可能还有一些问题,但是过程中感觉自己成长不少, 最后居然感觉对javascript事件机制有了更好的认识 ...

  3. javascript之-深入事件机制

    作者:yuyuyu链接:https://zhuanlan.zhihu.com/p/24620643来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 1.1 事件绑定的方式 ...

  4. 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)

    前言 这篇博客有点长,如果你是高手请您读一读,能对其中的一些误点提出来,以免我误人子弟,并且帮助我提高 如果你是javascript菜鸟,建议您好好读一读,真的理解下来会有不一样的收获 在下才疏学浅, ...

  5. javascript event(事件对象)详解

    javascript event(事件对象)详解   1. 事件对象     1. 事件对象 Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 什 ...

  6. JavaScript(1)---绑定事件、解除绑定事件

    JavaScript(1)---绑定事件.解除绑定事件 一.事件概述 1.事件的几个概念 · 事件 指的是文档或者浏览器窗口中发生的一些特定交互瞬间.我们可以通过侦听器(或者处理程序)来预定事件,以便 ...

  7. jQuery中的事件机制深入浅出

    昨天呢,我们大家一起分享了jQuery中的样式选择器,那么今天我们就来看一下jQuery中的事件机制,其实,jQuery中的事件机制与JavaScript中的事件机制区别是不大的,只是,JavaScr ...

  8. 【React】354- 一文吃透 React 事件机制原理

    大纲 主要分为4大块儿,主要是结合源码对 react事件机制的原理 进行分析,希望可以让你对 react事件机制有更清晰的认识和理解. 当然肯定会存在一些表述不清或者理解不够标准的地方,还请各位大神. ...

  9. react第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制)

    第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制) 课程目标 深入理解和掌握事件的冒泡及捕获机制 理解react中的合成事件的本质 在react组件中合理的使用原生事件 ...

随机推荐

  1. 关于ORACLE中配置文件的问题

    关于windows服务和oracle的问题的解决 <?xml version="1.0" encoding="utf-8"?><configu ...

  2. 【原创】Android内存管理-OnTrimMemory

    Application中有两个与内存管理相关的方法:onLowMemory()和 onTrimMemory(int level),源码如下 @CallSuper public void onLowMe ...

  3. Effective objective-c 2.0阅读笔记

    这本书非常的好,看完后,感触挺深,总结纪录一下,针对ios开发的备忘: 注:分类和原著有些不同,自己总结学习用的,仅供参考.   系统篇: 了解oc起源:继承c,由Smalltalk演化而来.动态语言 ...

  4. AngularJS-chapter2-7-前端路由

    Form表单提交会导致页面之间的切换,没法实现单页应用 Ajax请求不会留下History记录(在后台管理系统,没有后台历史记录还可以) ,但在网络型应用或门户型应用(用户没有办法给改页面加标签或分享 ...

  5. Android IOS WebRTC 音视频开发总结(八十一)-- WebRTC靠谱吗?有没有适合的SDK推荐?

    作者:blaker,最早发表在我们的微信公众和[编风网],详见[这里] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:blackerteam 或 webrtcorgcn) ...

  6. lnmp下启动mysql报错 The server quit without updating PID file

    启动时候错误代码:Starting MySQL[FAIL.] The server quit without updating PID file (/var/run/mysqld/mysqld.pid ...

  7. ArcGIS api fo silverlight学习二(silverlight加载GraphicsLayer)

    上一节学习了silverlight加载GeoServer发布的WMS地图,这一节学习一下加载GraphicsLayer 一.加载.png或jpg文件图标 1.在MainPage.xaml中添加资源配置 ...

  8. KMP算法分析

    KMP是一种复杂度较低的字符串比较算法.基本思路是对欲匹配字符串进行预处理,分析当k位匹配时可以后移的位数,所得的数构成该字符串的特征向量. 求特征向量Next int* Next(string p) ...

  9. WPF的二维绘图(二)——几何图形Geometry

    在WPF的DrawingContext对象中,提供了基本的绘制椭圆和矩形的API:DrawEllipse和DrawRectangle.但是,这些是远远不够用的,我们在日常应用中,更多的是使用DrawG ...

  10. VUE 入门基础(6)

    六,条件渲染 v-if 添加一个条件块 <h1 v-if="ok">Yes</h1> 也可以用v-else 添加else 块 <template> ...