带你快速理解javascript中的事件模型


Posted in Javascript onAugust 14, 2017

javascript中有两种事件模型:DOM0,DOM2。而对于这两种的时间模型,我一直不是非常的清楚,现在通过网上查阅资料终于明白了一些。

一.  DOM0级事件模型

DOM0级事件模型是早期的事件模型,所有的浏览器都是支持的,而且其实现也是比较简单。代码如下:

<p id = 'click'>click me</p>
<script>
 document.getElementById('click').onclick = function(event){
  alert(event.target);
 }
</script>

这种事件模型就是直接在dom对象上注册事件名称,这段代码就是在p标签上注册了一个onclick事件,在这个事件函数内部输出点击的目标。而解除事件则更加简单,就是将null复制给事件函数,如下:

document.getElementById('click'_).onclick = null;

由此我们可以知道dom0中,一个dom对象只能注册一个同类型的函数,因为注册多个同类型的函数的话,就会发生覆盖,之前注册的函数就会无效。

var click = document.getElementById('click');
click.onclick = function(){
 alert('you click the first function');
};
click.onclick = function(){
 alert('you click the second function')
}

在这段代码中,我们为dom对象注册了两个onclick函数,但是结果是只执行了第二个注册的函数,前面所注册的函数被覆盖了。

二.   DOM2级事件模型

1.  事件捕获和事件冒泡(capture,bubble)

首先,IE8及以下是不支持这种事件模型的。事件捕获和事件冒泡的机制如下图:

带你快速理解javascript中的事件模型

如上图所示,123代表事件捕获,4567代表事件冒泡。首先我们使用下面的代码:

<div id = 'outer' style = 'margin: 100px 0 0 100px; width: 200px;height: 200px; background: red;'>
 <div id="inner" style = 'margin-left:20px; width: 50px;height:50px; background: green;'></div>
</div>

假设我们点击了ID为inner的div,那么此时的事件流程就是,首先执行捕获阶段:document-html-body-div(outer)。然后执行冒泡阶段:div(inner)-div(outer)-body-html-document。

  2.   DOM2级的注册事件和解除事件

在DOM2级中使用addEventListener和removeEventListener来注册和解除事件(IE8及之前版本不支持)。这种函数较之之前的方法好处是一个dom对象可以注册多个相同类型的事件,不会发生事件的覆盖,会依次的执行各个事件函数。

addEventListener('事件名称','事件回调','捕获/冒泡')。示例如下:

<div id = 'outer' style = 'margin: 100px 0 0 100px; width: 200px;height: 200px; background: red;'>
 <div id="inner" style = 'margin-left:20px; width: 50px;height:50px; background: green;'></div>
</div>
<script>
 var click = document.getElementById('inner');
 click.addEventListener('click',function(){
  alert('click one');
 },false);
 click.addEventListener('click',function(){
  alert('click two');
 },false);
</script>

首先我们要知道addEventListenr的第一个参数是事件名称,与DOM0级不同的是没有”on“,另外第三个参数代表捕获还是冒泡,true代表捕获事件,false代表冒泡事件。

而在这段代码中,我们为inner的div注册了两个click事件函数,结果是浏览器会依次执行这两个函数。

下面我们演示如何使用事件流的发生机制。

<div id = 'outer' style = 'margin: 100px 0 0 100px; width: 200px;height: 200px; background: red;'>
 <div id="inner" style = 'margin-left:20px; width: 50px;height:50px; background: green;'></div>
</div>
<script>
 var click = document.getElementById('inner');
 var clickouter = document.getElementById('outer');
 click.addEventListener('click',function(){
  alert('inner show');
 },true);
 clickouter.addEventListener('click',function(){
  alert('outer show');
 },true);
</script>

这段代码,我们使用了捕获事件,由于inner是嵌套在outer中的,所以我们知道当使用捕获的时候outer是应该首先捕获到这个事件的,其次inner才能捕获到这个事件。那么结果就是outer首先执行,其次是inner执行。

那么我把outer的执行时机改为冒泡的阶段呢?

alickouter.addEventListener('click',function(){
 alert('outer show'); 
},false);

这种情况下,就是先执行inner后执行outer了。同理我们把二者的事件执行时机都改为冒泡阶段的话,依旧是先执行inner后执行outer。那么还有个问题,就是如果我们把inner注册两个click事件,一个是在捕获阶段,另一个是在冒泡阶段,也就是说把addEventListenter的第三个参数分别设置为false和true,那么执行的顺序又是怎样的呢。

<script>
 var click = document.getElementById('inner');
 var clickouter = document.getElementById('outer');
 click.addEventListener('click',function(){
  alert('capture show');
 },true);
 click.addEventListener('click',function(){
  alert('bubble show');
 },false);
</script>

这种情况下首先这些的是capture show,其次是bubble show。但是这种结果是与注册的顺序有关系的,先注册就先执行。因为我们在看事件捕获和事件冒泡示意图,发现最后具体的dom对象是只有一个的。

那么 如果我们给outer和inner都注册了click事件但是我不希望outer执行怎么办呢?这个时候我们就需要用到stopPropagation函数了,这个函数是用来阻止冒泡,言下之意是让事件不再继续冒泡下去,这样接下来注册同样类型事件的dom对象就不会执行了。

比如在自制下拉框的时候,我们点击浏览器的其他位置,我们需要下拉框的options隐藏,这时我们就要用到stopPropagation了。如下:

<script>
 var click = document.getElementById('inner');
 var clickouter = document.getElementById('outer');
 click.addEventListener('click',function(event){
  alert('inner show');
  event.stopPropagation();
 },false);
 clickouter.addEventListener('click',function(){
  alert('outer show');
 },false);
</script>

正常的情况下,我们在不添加stopPropagation函数时,首先应该执行inner,然后执行outer,但是当我们在inner的事件函数中添加了stopPropagation函数之后,执行完inner的事件函数之后,就不会在执行outer的事件函数了,也可以理解为事件冒泡到inner之后就消失了,因此也就不会在执行接下来的事件函数了。

由于事件捕获阶段没有可以阻止事件的函数,所以一般都是设置为事件冒泡。

好了以上就是全部内容啦 ,希望对大家的学习有所帮助~~

Javascript 相关文章推荐
jQuery实现二级下拉菜单效果
Jan 05 Javascript
JavaScript算法系列之快速排序(Quicksort)算法实例详解
Sep 04 Javascript
省市区三级联动jquery实现代码
Apr 15 Javascript
JS实现全屏的四种写法
Dec 30 Javascript
js实现自定义路由
Feb 04 Javascript
laydate 显示结束时间不小于开始时间的实例
Aug 11 Javascript
详解vue-cli脚手架build目录中的dev-server.js配置文件
Nov 24 Javascript
微信小程序Flex布局用法深入浅出分析
Apr 25 Javascript
es6中let和const的使用方法详解
Feb 24 Javascript
vue-router定义元信息meta操作
Dec 07 Vue.js
Node.js实现断点续传
Jun 23 Javascript
浅谈Vue的computed计算属性
Mar 21 Vue.js
JS获取子、父、兄节点方法小结
Aug 14 #Javascript
JS传播事件、取消事件默认行为、阻止事件传播详解
Aug 14 #Javascript
JS如何实现在页面上快速定位(锚点跳转问题)
Aug 14 #Javascript
JavaScript实现动态添加Form表单元素的方法示例
Aug 14 #Javascript
JavaScript实现的搜索及高亮显示功能示例
Aug 14 #Javascript
带你了解session和cookie作用原理区别和用法
Aug 14 #Javascript
react.js使用webpack搭配环境的入门教程
Aug 14 #Javascript
You might like
PHP学习笔记之三 数据库基本操作
2011/01/17 PHP
基于linnux+phantomjs实现生成图片格式的网页快照
2015/04/15 PHP
PHP7新功能总结
2019/04/14 PHP
jquery tools系列 expose 学习
2009/09/06 Javascript
JavaScript 反科里化 this [译]
2012/09/20 Javascript
javascript获取网页中指定节点的父节点、子节点的方法小结
2013/04/24 Javascript
jquery实现图片按比例缩放示例
2014/07/01 Javascript
解决js图片加载时出现404的问题
2020/11/30 Javascript
分享一些常用的jQuery动画事件和动画函数
2015/11/27 Javascript
JavaScript笔记之数据属性和存储器属性
2016/03/31 Javascript
BootStrap给table表格的每一行添加一个按钮事件
2017/09/07 Javascript
使用Webpack提升Vue.js应用程序的4种方法(翻译)
2019/10/09 Javascript
基于vue和bootstrap实现简单留言板功能
2020/05/30 Javascript
[03:03]2014DOTA2国际邀请赛 EG战队专访
2014/07/12 DOTA
[46:40]VGJ.T vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
python中实现定制类的特殊方法总结
2014/09/28 Python
Python ValueError: invalid literal for int() with base 10 实用解决方法
2015/06/21 Python
用Cython加速Python到“起飞”(推荐)
2019/08/01 Python
Python3 JSON编码解码方法详解
2019/09/06 Python
opencv+python实现均值滤波
2020/02/19 Python
CSS中越界问题的经典解决方案【推荐】
2016/04/19 HTML / CSS
moosejaw旗下的户外商品促销网站:Mountain Steals
2017/02/27 全球购物
西班牙第一的网上药房:PromoFarma.com
2017/04/17 全球购物
Topman美国官网:英国著名的国际平价时尚男装品牌
2017/12/22 全球购物
Arti-shopping中文官网:大型海外商品一站式直邮平台
2020/03/23 全球购物
俄罗斯第一家篮球店:StreetBall
2020/07/30 全球购物
岗位竞聘演讲稿
2014/01/10 职场文书
缓刑人员的思想汇报
2014/01/11 职场文书
高三政治教学反思
2014/02/06 职场文书
2015年元旦活动总结
2014/05/09 职场文书
党的群众路线教育实践活动党员个人剖析材料
2014/10/08 职场文书
单位接收函范文
2015/01/30 职场文书
全国爱眼日活动总结
2015/02/27 职场文书
CocosCreator入门教程之网络通信
2021/04/16 Javascript
Ajax是什么?Ajax高级用法之Axios技术
2021/04/21 Javascript
vue首次渲染全过程
2021/04/21 Vue.js