一、开篇

在学习javascript之初,就在网上看过不少介绍javascript事件的文章,毕竟是js基础中的基础,文章零零散散有不少,但遗憾的是没有看到比较全面的系列文章。犹记得去年这个时候,参加百度的实习生面试,被问到事件模型,当时被问的一头雾水,平时敲onclick敲的挺爽,却没有关注到事件模型的整体概念。这个周末难得清闲,决定就javascript中的事件模型写个系列,算是对知识点的一个总结,也是对自己的一个交代。

初步计划分为以下几个部分:

    ①   javascript事件的基本概念及基于原始、IE、DOM2的三种模型的异同点

    ②   javascript事件流介绍,捕获-冒泡机制及事件委托机制

    ③   jquery中的事件监听方式(bind、live、attachEvent、on)及异同点

    ④   javascript自定义事件

二、event简介

什么是事件呢?直观的说就是网页上发生的事情,大部分是指用户的鼠标动作和键盘动作,如点击、移动鼠标、按下某个键。为什么说大部分呢,因为事件不单单只有这两部分,还有其他的例如document的load和unloaded。只不过我们更加关注的是用户的操作。事件被封装成一个event对象,包含了该事件发生时的所有相关信息(event的属性)以及可以对事件进行的操作(event的方法)。

event长啥样呢,来直观的看一下,比如我点击页面上一个按钮,产生的event对象如下:

可以看到是一个MouseEvent对象,包含了一系列属性,如鼠标点击的位置等。那么敲击键盘时产生的event对象和它一样吗?看看就知道:

    可以看到是一个KeyboardEvent对象,并且属性跟上面的也不太一样,如没有clientX/Y,那是理所当然的啦,敲键盘怎么能获取到鼠标的位置呢。

若你有一点面向对象编程的基础,看到这两个类名应该会有所思考,MouseEvent、KeyboardEvent会不会是继承自一个叫Event的类呢?恭喜你猜对了,确实如此。来看一下,我在window.onload监听函数中打印出event对象如下:

    属性少了很多,毕竟是父类嘛。若你想了解更多关于事件类型的内容,可以参考这里,本文就不做更深的介绍。

三、event对象常用属性、方法

1. 事件定位相关属性

    这部分属性平时用的还是挺多的,所以得着重介绍。如果你细细看了MouseEvent对象里的属性,一定发现了有很多带X/Y的属性,它们都和事件的位置相关。具体包括:x/y、clientX/clientY、pageX/pageY、screenX/screenY、layerX/layerY、offsetX/offset 六对。有点乱了吧,一个点击事件能有多少位置啊?不要着急,其实并不复杂,之所以能有这么多是因为各浏览器厂商在版本更迭的时候产生了很多不一致。看下面的例子就明白各自的含义了:

在这里移动鼠标
x:   y:
clientX:   clientY:
screenX:   screenY:
offsetX:   offsetY:
pageX:   pageY:
layerX:   layerY:

    得出的结论如下:

    x/y与clientX/clientY值一样,表示距浏览器可视区域(工具栏除外区域)左/上的距离;

    pageX/pageY,距页面左/上的距离,它与clientX/clientY的区别是不随滚动条的位置变化;

    screenX/screenY,距计算机显示器左/上的距离,拖动你的浏览器窗口位置可以看到变化;

    layerX/layerY与offsetX/offsetY值一样,表示距有定位属性的父元素左/上的距离。

    之所以有那么多值一样的情况,就是由于浏览器兼容的原因。那我们平时该如何使用呢?请看下面的表格,列出了各属性的浏览器支持情况。(+支持,-不支持)

    offsetX/offsetY:W3C- IE+ Firefox- Opera+ Safari+ chrome+

    x/y:W3C- IE+ Firefox- Opera+ Safari+ chrome+

    layerX/layerY:W3C- IE- Firefox+ Opera- Safari+ chrome+

    pageX/pageY:W3C- IE- Firefox+ Opera+ Safari+ chrome+

    clientX/clientY:W3C+ IE+ Firefox+ Opera+ Safari+ chrome+

    screenX/screenY:W3C+ IE+ Firefox+ Opera+ Safari+ chrome+​

  说明:该表摘自其他文章,我未做全部验证,但从最新版本的现代浏览器来看,这些属性貌似是都支持了,为了更好的兼容性,通常我们选择W3C支持的就可以了。若你想看更加细致的相关描述,请点击这里。

2.其他常用属性

    target:发生事件的节点;

    currentTarget:当前正在处理的事件的节点,在事件捕获或冒泡阶段;

      timeStamp:事件发生的时间,时间戳。

    bubbles:事件是否冒泡。

    cancelable:事件是否可以用preventDefault()方法来取消默认的动作;

    keyCode:按下的键的值;

3. event对象的方法

    event. preventDefault()//阻止元素默认的行为,如链接的跳转、表单的提交;

    event. stopPropagation()//阻止事件冒泡

    event.initEvent()//初始化新事件对象的属性,自定义事件会用,不常用

    event. stopImmediatePropagation()//可以阻止掉同一事件的其他优先级较低的侦听器的处理,(我没有用过)

四、事件的三种模型

由于复杂的历史原因,事件模型是不统一的,当然作为前端开发人员这种事情已经见怪不怪了。尽管W3C已经制定了DOM2标准来规范事件的定义,但由于顽固的IE6、7、8存在,我们还是得清楚IE的那一套定义。那么来看看三种模型都有哪些吧。

1.     原始事件模型

    在原始事件模型中(也有说DOM0级),事件发生后没有传播的概念,没有事件流。事件发生,马上处理,完事,就这么简单。监听函数只是元素的一个属性值,通过指定元素的属性值来绑定监听器。书写方式有两种:

    ①   HTML代码中指定属性值:<input type=”button” οnclick=”func1()” />

    ②   在js代码中指定属性值:document.getElementsByTagName(‘input’)[0].onclick = func1

    优点:所有浏览器都兼容

    缺点:1)逻辑与显示没有分离;2)相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面的,如:a.onclick = func1; a.onclick = func2;将只会执行func2中的内容。3)无法通过事件的冒泡、委托等机制(后面系列会讲到)完成更多事情。

    在当前web程序模块化开发以及更加复杂的逻辑状况下,这种方式显然已经落伍了,所以在真正项目中不推荐使用,平时写点博客小例子啥的倒是可以,速度比较快。

2.     IE事件模型

    在参考其他资料时,我有看到这样的一句话“IE不把该对象传入事件处理函数,由于在任意时刻只会存在一个事件,所以IE把它作为全局对象window的一个属性”,为求证其真伪,我用IE8执行了代码alert(window.event),结果弹出是null,说明该属性已经定义,只是值为null(与undefined不同)。我想难道这个全局对象的属性是在监听函数里才加的?于是执行下面代码:

    window.onload = function (){alert(window.event);}

    setTimeout(function(){alert(window.event);},2000);

    结果第一次弹出【object event】,两秒后弹出依然是null。由此可见IE是将event对象在处理函数中设为window的属性,一旦函数执行结束,便被置为null了。IE的事件模型只有两步,先执行元素的监听函数,然后事件沿着父节点一直冒泡到document。冒泡机制后面系列会讲,此处暂记。IE模型下的事件监听方式也挺独特,绑定监听函数的方法是:attachEvent( "eventType","handler"),其中evetType为事件的类型,如onclick,注意要加’on’。解除事件监听器的方法是 detachEvent("eventType","handler" )

    IE的事件模型已经可以解决原始模型的三个缺点,但其自己的缺点就是兼容性,只有IE系列浏览器才可以这样写。

3.     DOM2事件模型

    此模型是W3C制定的标准模型,既然是标准,那大家都得按这个来,我们现在使用的现代浏览器(指IE6~8除外的浏览器)都已经遵循这个规范。W3C制定的事件模型中,一次事件的发生包含三个过程:

    (1)capturing phase:事件捕获阶段。事件被从document一直向下传播到目标元素,在这过程中依次检查经过的节点是否注册了该事件的监听函数,若有则执行。

    (2)target phase:事件处理阶段。事件到达目标元素,执行目标元素的事件处理函数.

    (3)bubbling phase:事件冒泡阶段。事件从目标元素上升一直到达document,同样依次检查经过的节点是否注册了该事件的监听函数,有则执行。

    所有的事件类型都会经历captruing phase但是只有部分事件会经历bubbling phase阶段,例如submit事件就不会被冒泡。

    你可能会有疑问,为什么是这个样子的呢?流程有点太多了吧?事情的缘由还得从网景公司与微软争霸开始说起。在W3C的规范还没有出生的时候,市场上已经有两家强劲的浏览器厂商,产品分别是微软的IE和网景的Netspace Navigator(后面简称NN),IE的事件模型上面已介绍,事件是可以冒泡的。然而NN却不这么认为,它的模型中,事件是从上往下走的,即只有捕获阶段。两家都没有谁对谁错,因为按照他们的模型都可以完成事件的处理。然后W3C珊珊来迟,要制定标准,要统一,所以也就只能两家的都采纳,谁也不得罪,然后用标准制定者的口吻宣布:W3C模型工作良好。从此天下太平。

    说远了,赶紧来看看标准的事件监听器该如何绑定:addEventListener("eventType","handler","true|false");其中eventType指事件类型,注意不要加‘on’前缀,与IE下不同。第二个参数是处理函数,第三个即用来指定是否在捕获阶段进行处理,一般设为false来与IE保持一致,除非你有特殊的逻辑需求。监听器的解除也类似:removeEventListner("eventType","handler","true!false");

        以上便是事件的三种模型,我们在开发的时候需要兼顾IE与非IE浏览器,所以注册一个监听器应该这样写:

var a = document.getElementById('a');
if(a.attachEvent){a.attachEvent('onclick',func);
}
else{a.addEventListener('click',func,false);
}

  感觉很麻烦吧?因此我们一般会借助现有框架或类库已经封装好的,比如jQuery,后面将会介绍jQuery中强大的事件监听方式。

    系列一到此结束,作者本人技术水平有限,文章内容都是自己的理解写出来的,欢迎各路高手指点纠错。

Javascript事件模型系列(一)事件及事件的三种模型相关推荐

  1. (03)_k8s之flannel三种模型安装部署详解

    flannel三种模型安装部署详解 yht_1990关注[2020-10-04 12:13:47](javascript:

  2. Java 三种模型,四种策略

    Java 三种模型,四种策略 (转) 混淆事务模型与事务策略是一个常见的错误.本系列关于 事务策略 的第二篇文章将概述 Java™ 平台支持的三种事务模型,并介绍使用这些模型的四种主要事务策略.通过使 ...

  3. 产品路线图的三种模型(RICE/MoSCoW/Kano),教你如何对需求进行优先级排序

    前言 RICE/MoSCoW/Kano三种模型,教你如何对需求进行优先级排序. 也许你会让业务提供一份ROI,记得前不久参加过一场立项会评审,一位很有意思的小产品在会上讲不清楚ROI,评审们要求会后重 ...

  4. 第三天2017/03/30(上午:二级指针的(输入)内存模型:(共三种模型))

    二级指针 char a[10][10]; char (*a)[10]; char *a[10]; char **a; char **a; char **a; 字符数组的操作易犯错误: 1.字符数组在使 ...

  5. word2vec模型评估_NLP之文本分类:「Tf-Idf、Word2Vec和BERT」三种模型比较

    字幕组双语原文:NLP之文本分类:「Tf-Idf.Word2Vec和BERT」三种模型比较 英语原文:Text Classification with NLP: Tf-Idf vs Word2Vec ...

  6. JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别

    JavaScript:学习笔记(7)--VAR.LET.CONST三种变量声明的区别 ES2015(ES6)带来了许多闪亮的新功能,自2017年以来,许多JavaScript开发人员已经熟悉并开始使用 ...

  7. 运用自回归滑动平均模型、灰色预测模型、BP神经网络三种模型分别预测全球平均气温,并进行预测精度对比(附代码、数据)

    大家好,我是带我去滑雪,每天教你一个小技巧!全球变暖是近十年来,人们关注度最高的话题.2022年夏天,蔓延全球40℃以上的极端天气不断刷新人们对于高温的认知,人们再也不会像从前那样认为全球变暖离我们遥 ...

  8. UML建模(三种模型)

    文章目录 一.UML建模(三种模型) 1.类模型 2.状态模型 3.交互模型 二.uml建模的步骤 一.UML建模(三种模型) 1.类模型 描述系统内部对象及其关系的静态结构.类模型由类图构建,类图中 ...

  9. bert模型可以做文本主题识别吗_NLP之文本分类:「Tf-Idf、Word2Vec和BERT」三种模型比较...

    字幕组双语原文:NLP之文本分类:「Tf-Idf.Word2Vec和BERT」三种模型比较 英语原文:Text Classification with NLP: Tf-Idf vs Word2Vec ...

最新文章

  1. 静态路由和默认路由的区别
  2. Python + Selenium 练习篇 - 获取页面所有邮箱
  3. visual studio快捷键 Qt creator快捷键
  4. python入门之函数结构函数的参数_python3基础之函数参数类型
  5. java 匿名函数_国外程序员用的火热的Vavr是什么鬼?让函数式编程更简单!
  6. mysql存储过程应用_mysql 存储过程的应用
  7. linux安装bash工具包,Linux 资源监视工具BashTop的安装和使用
  8. 如何真正让小程序,WebRTC和APP互通连麦直播
  9. 【ENVI预处理】辐射校正、影像配准、图像融合、图像镶嵌 、图像裁剪、图像增强
  10. Hibernate方法save、update、merge、saveOrUpdate及get和load的区别
  11. 最新可乐云商城程序源码V0.6版本 可做实物商城网站
  12. 2019年 年终总结
  13. Vue使用Echarts控件实现图表设计
  14. 估值篇之最关键指标ROE
  15. Android 百度语音合成手把手教学
  16. 爬虫抓包问题全面分析
  17. JavaScript原生实现广告栏滑动
  18. SML-Abridgelab
  19. 根据身份证号或营业执照编号取省市区信息
  20. 【dqmp项目笔记】

热门文章

  1. win8恢复我的计算机较早时间点,Win8系统的重置和刷新功能 -电脑资料
  2. 20191001:String,StringBuffer,StringBuilder类异同辨析
  3. html%3c arial%3e,【博客园】样式美化+网站统计访问+添加网易云背景音乐
  4. 反应机理_介绍一种化学反应机理合成环戊酮
  5. postman请求参数区别
  6. MIPI - DVP
  7. 心语收集13:有时候我真想忘了你,只记得这个世界,然而,我常常忘了整个世界,只记得你。...
  8. 谷歌大脑小姐姐亲授:如何应聘成功羡煞旁人的AI工程师岗位
  9. 银河水滴打响步态识别商用第一枪!3大产品1.35亿订单,工业视觉平台免费开放...
  10. Quoc Le,谷歌AutoML的幕后英雄