带你快速理解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 相关文章推荐
js option删除代码集合
Nov 12 Javascript
jquery mobile实现拨打电话功能的几种方法
Aug 05 Javascript
jquery中$each()方法的使用指南
Apr 30 Javascript
JavaScript Length 属性的总结
Nov 02 Javascript
浅谈javascript:两种注释,声明变量,定义函数
Oct 05 Javascript
js+html制作简单日历的方法
Jun 27 Javascript
原生JS实现轮播图效果
Oct 12 Javascript
使用vue2.6实现抖音【时间轮盘】屏保效果附源码
Apr 24 Javascript
微信小程序自定义tabbar custom-tab-bar 6s出不来解决方案(cover-view不兼容)
Nov 01 Javascript
如何在Vue中使localStorage具有响应式(思想实验)
Jul 14 Javascript
js+css实现扇形导航效果
Aug 18 Javascript
关于Js中new操作符的作用详解
Feb 21 Javascript
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版(4)
2006/10/09 PHP
php 数组的指针操作实现代码
2011/02/08 PHP
用PHP书写安全的脚本代码
2012/02/05 PHP
php DOS攻击实现代码(附如何防范)
2012/05/29 PHP
解析PHP实现下载文件的两种方法
2013/07/05 PHP
PHP实现将视频转成MP4并获取视频预览图的方法
2015/03/12 PHP
PHP数组相关函数汇总
2015/03/24 PHP
php判断一个数组是否为有序的方法
2015/03/27 PHP
PHP中的魔术方法总结和使用实例
2015/05/11 PHP
PHP hex2bin()函数用法讲解
2019/02/25 PHP
gearman中任务的优先级和返回状态实例分析
2020/02/27 PHP
PHP延迟静态绑定使用方法实例解析
2020/09/05 PHP
利用jQuery的$.event.fix函数统一浏览器event事件处理
2009/12/21 Javascript
javascript学习笔记(一)基础知识
2014/09/30 Javascript
关于backbone url请求中参数带有中文存入数据库是乱码的快速解决办法
2016/06/13 Javascript
jQuery+ajax实现实用的点赞插件代码
2016/07/06 Javascript
jquery 判断selection range 是否在容器中的简单实例
2016/08/02 Javascript
浅析JavaScript中break、continue和return的区别
2016/11/30 Javascript
javascript 面向对象function详解及实例代码
2017/02/28 Javascript
微信小程序 实现点击添加移除class
2017/06/12 Javascript
javascript基于定时器实现进度条功能实例
2017/10/13 Javascript
微信小程序自定义toast实现方法详解【附demo源码下载】
2017/11/28 Javascript
移动端滑动切换组件封装 vue-swiper-router实例详解
2018/11/25 Javascript
[01:38]DOTA2辉夜杯 欢乐的观众现场采访
2015/12/26 DOTA
python下10个简单实例代码
2017/11/15 Python
Python 和 JS 有哪些相同之处
2017/11/23 Python
在Pycharm中自动添加时间日期作者等信息的方法
2019/01/16 Python
Python面向对象之Web静态服务器
2019/09/03 Python
如何理解python面向对象编程
2020/06/01 Python
利用css3-animation实现逐帧动画效果
2016/03/10 HTML / CSS
Evisu官方网站:日本牛仔品牌,时尚街头设计风格
2016/12/30 全球购物
班级入场式解说词
2014/02/01 职场文书
语文教学感言
2014/02/06 职场文书
普通简短的个人自我评价
2014/02/15 职场文书
毕业设计论文致谢词
2015/05/14 职场文书
MySQL 表锁定 LOCK和UNLOCK TABLES的 SQL语法
2022/04/18 MySQL