在线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. JVM 内存的那些事

    转自:http://blog.jobbole.com/104863/ 对于Java程序员你来说,在虚拟机内存管理的帮助下,不需要为每个new对象都匹配free操作,内存泄露和内存溢出等问题也不太容易出 ...

  2. CodeSmith7代码生成器针对PostgreSQL数据库无法使用的Bug修复全过程

    前言 最近公司需要将原来使用的MSSQL数据库整体迁移至pgsql,需要使用CodeSmith生成IBatisNet的配置文件.按照提示安装了Npgsql.dll后依然无法使用.引发了本次通过反编译修 ...

  3. cat > file << EOF 的用法

    cat> 文件名<<eof 用来创建文件在这之后输入任何东西 都是在 文件里的输入完成之后EOF结尾 代表结束比如cat > 1.txt <<eof12345eof ...

  4. AC 设置DMZ口上网

  5. ue4 c++ 接口

    使用UE4接口比起普通的高级语言,要多做很多工作,是因为要兼容蓝图的使用,有一些小坑需要注意,开始吧. 1.新建接口类 打开UE4编辑器,与往常一样,新建C++类,然后选择Object继承,然后取名字 ...

  6. JAVA-系统-【2】-创建自增长的用户表

    [2]创建数据库表  用户表 自增 1.用户表结构  数据excel 表1 2.创建表 Create table A_USER( id number primary key, username ) n ...

  7. assert的用法

    assert用来调试时,判断一个语句是否为真. assert是宏,而不是函数.在C的assert.h 头文件中. assert的作用是先计算表达式 expression ,如果其值为假(即为0),那么 ...

  8. Managing IIS Log File Storage

    Managing IIS Log File Storage   You can manage the amount of server disk space that Internet Informa ...

  9. xargs的原理剖析及用法详解

    转载请注明出处:http://www.cnblogs.com/f-ck-need-u/p/5925923.html 学习这个xargs花了很长时间,在网上翻了很久也查了很多书关于xargs的介绍,都只 ...

  10. ubuntu文本模式/终端中文乱码解决

    ubuntu文本模式/终端中文乱码解决 1.Alt+Ctrl+F1 进入第一个终端tty1,发现中文乱码. 2.安装zhcon. sudo apt-get install zhcon3 输入下面命令, ...