《javascript高级程序设计》跨浏览器事件处理程序EventUtil.js个人注释

EventUtil.js

// 跨浏览器事件处理程序封装
var EventUtil = {// 添加事件句柄addHandler: function(element, type, handler){// DOM 2 级事件处理程序if (element.addEventListener){element.addEventListener(type, handler, false);}// IE事件处理程序else if (element.attachEvent){element.attachEvent("on" + type, handler);} // DOM 0 级事件处理程序else{element["on" + type] = handler;}},// 获取鼠标事件button属性 ,// 0:主鼠标按钮    // 1:中间按钮        // 2:次鼠标按钮getButton: function(event){// DOM Button属性if(document.implementation.hasFeature("MouseEvents", "2.0")){return event.button;}// IE 模式下的button属性else{switch(event.button){case 0:case 1:case 3:case 5:case 7:return 0;case 2:case 6:return 2;case 4: return 1;}}},// 获取键盘事件keypress事件的charCode属性// 该值表示按下的键所代表的ASCII码getCharCode: function(event){// IE9 FireFox Chrome Safariif(typeof event.getCharCode == "number"){return event.charCode;}// IE8 Operaelse{return event.keyCode;}},// 获取剪切板内容getClipboardText: function(event){var clipboardData =  (event.clipboardData || window.clipboardData);return clipboardData.getData("text");},// 获取事件对象getEvent: function(event){return event ? event : window.event;},// 获取relatedTarget属性// 在mouseover事件触发时,IE的fromElement属性中保存了相关元素;// 在mouseout事件触发时,IE的toElement属性中保存了相关元素getRelatedTarget: function(event){// DOM属性,IE8不支持if (event.relatedTarget){return event.relatedTarget;} // IE mouseoutelse if (event.toElement){return event.toElement;} // IE mouseoverelse if (event.fromElement){return event.fromElement;} else {return null;}},// 获取target事件对象getTarget: function(event){// DOM || IEreturn event.target || event.srcElement;},// 获取鼠标滚轮滚动时的属性值getWheelDelta: function(event){// IE6.0 Chrome  Opera  Safari wheelData属性值// 向前滚动是120的倍数// 向后滚动是-120的倍数if (event.wheelDelta){return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);} // Firefox detail属性值// 向前滚动是-3的倍数// 向后滚动是3的倍数else {return -event.detail * 40;}},// 取消事件的默认行为preventDefault: function(event){// DOMif (event.preventDefault){event.preventDefault();} // IEelse {event.returnValue = false;}},// 移除事件句柄removeHandler: function(element, type, handler){// DOM 2if (element.removeEventListener){element.removeEventListener(type, handler, false);} // IEelse if (element.detachEvent){element.detachEvent("on" + type, handler);} // DOM 0else {element["on" + type] = null;}},// 设置剪切板内容setClipboardText: function(event, value){// Chromeif (event.clipboardData){event.clipboardData.setData("text/plain", value);} // IEelse if (window.clipboardData){window.clipboardData.setData("text", value);}},// 取消事件冒泡stopPropagation: function(event){// DOMif (event.stopPropagation){event.stopPropagation();}// IEelse {event.cancelBubble = true;}}};

  

详细说明:

addHandler方法

这是EventUtil中最常用的方法,它的作用是为对象添加事件并保证兼容性

在DOM0级事件处理程序(下文均简称“DOM0级”)中

每个元素(包括windows和document)都有自己的事件处理程序属性(通常全部小写)

如常见的onload、onclick等

以Click事件为例(下同),DOM0级通常如下指定事件处理程序

1 var btn=document.getElementById("myBtn");
2 btn.οnclick=function(){ //指定事件处理程序
3    alert(this.id);      //"myBtn"
4 };

在DOM2级事件处理程序(下文均简称“DOM2级”)中

指定事件处理程序的方法为addEventListener( )

它接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值(大多数情况下是false)

(布尔值表示是在捕获阶段(true)还是冒泡阶段(false)调用事件处理程序)

DOM2级通常如下指定事件处理程序

1 var btn=document.getElementById("myBtn");
2 //在外部定义好函数再传给addEventListener(),这样才可以通过removeEventListener()移除
3 var handler=function(){
4    alert(this.id);
5 };
6 btn.addEventListener("click",handler,false);

在旧版本IE(代表IE8-,下文均简称“IE”)中

指定事件处理程序的方法为attachEvent( )

它接受两个参数:事件处理程序名称与事件处理程序函数

IE中通常如下指定事件处理程序

1 var btn=document.getElementById("myBtn");
2 var handler=function(){
3    alert("Clicked");
4 };
5 //注意:第一个参数是"onclick",而非DOM0的addEventListener()方法中的"click"
6 btn.attachEvent("onclick",handler);

由上可见,DOM0级、DOM2级和IE中指定事件方法有很大不同

EventUtil对象中的addHandler方法正是为了处理这些差异而存在

在添加了EventUtil(指上文“EventUtil对象全见”中的代码,下同)后,可以如下所示为对象指定事件处理程序

1 var btn=document.getElementById("myBtn");
2 var handler=function(){
3    alert("Clicked!");
4 };
5 EventUtil.addHandler(btn,"click",handler);  //调用已定义的EventUtil对象

就像这样,使用addHandler方法指定事件处理程序

即可兼容支持DOM0级、DOM2级的浏览器或IE浏览器

removeHandler方法

同样的,在DOM0级、DOM2级与IE中,移除事件的方法是不同的

在DOM0级中,在不再需要某对象的事件处理程序时(如页面销毁前),可以像下面这样简单的移除事件处理程序

btn.οnclick=null;

在DOM2级中,删除事件处理程序需要使用removeEventListener( )方法,如下所示

1 //这里的handler应与使用addEventListener指定事件处理函数时所用的外部函数相同

2 btn.removeEventListener("click",handler,fals

而在IE中,删除事件则需使用detachEvent( )方法

btn.detachEvent("onclick",handler); 

因为这些差异的存在,才令EventUtil中有了removeHandler方法

在添加了EventUtil后,可以如下所示使用removeHandler方法方便地删除对象事件处理程序

1 //同样的,这里的handler应与使用addHandler指定事件处理函数时所用的外部函数相同

2 EventUtil.removeHandler(btn,"click",hanlder);

event对象与getEvent方法

你可能已经发现了,在EventUtil中,很多方法的参数都是event

这个event其实是事件对象

兼容DOM(无论是DOM0级还是DOM2级)的浏览器会将一个event对象传入到事件处理程序中

这个event对象支持许多方法,下表列出了一些常用的方法以供参考

属性/方法 类型 读/写 说明
currentTarget Element 只读 其事件处理程序当前正在处理事件的那个元素
preventDefault( ) Function 只读 取消事件的默认行为
stopPropagation( ) Function 只读 取消事件的进一步捕获或冒泡
target Element 只读 事件的实际(真正)目标
type String 只读 被触发的事件的类型

在兼容DOM的浏览器中,event对象可以如下面这个例子这样使用

 1 var btn=document.getElementById("myBtn");2 var handler=function(event){3    switch(event.type){      //使用event.type检测事件类型4       case "click":         //若是Click事件5          alert("Clicked");6          break;7       case: "mouseover":    //若是Mouseover事件8          //使用event.target获取事件目标,并更改目标样式背景颜色9          event.target.style.backgroundColor="red";
10          break;
11       case: "mouseout":     //若是Mouseout事件
12          event.target.style.backgroundColor="";
13          break;
14    }
15 };
16 btn.οnclick=handler;  //使用DOM0级为对象添加事件处理函数
17 btn.οnmοuseοver=handler;
18 btn.οnmοuseοut=handler;

需要强调的是,以上使用event事件的方法仅适用于兼容DOM的浏览器

在IE中则有所不同

在IE中,使用DOM0级添加事件处理程序时,event对象作为window对象的一个属性存在,如下例子所示

1 btn.οnclick=function(){
2    var event=window.event;
3    alert(event.type);  //"click"
4 };

神奇的是,如果事件处理程序是使用attachEvent( )添加的,则又可以像在支持DOM的浏览器中一样

event对象又可作为参数传入事件处理程序函数中,如下例子所示

1 btn.attachEvent("onclick",function(event){ 2 alert(event.type); //"click" 3 });

而且,更神奇的是,在IE中,event对象的一些属性/方法还跟其它支持DOM的浏览器中不同,如下表

属性/方法 类型 读/写 说明
cancelBubble Boolean 读/写 默认值为false,将其设置为true就可以取消事件冒泡
(与DOM中的stopPropagation( )方法的作用相同)
returnValue Boolean 读/写 默认值为true,将其设置为false就可以取消事件的默认行为
(与DOM中的preventDefault( )方法的作用相同)
srcElement Element 只读 事件的目标(与DOM中的target属性相同)
type String 只读 被触发的事件类型

正是因为这些差异的存在,使得EventUtil中的getEvent方法应运而生

在添加了EventUtil后,可以如下“重点语句”所示获取event对象而无需担心上述差异导致的兼容问题

1 var btn=document.getElementById("myBtn");
2 var handler=function(event){
3    event=EventUtil.getEvent(event); //重点语句
4 };
5 EventUtil.addHandler(btn,"click",handler); 

这样,就解决了event对象获取方式不同的问题

至于event对象的属性/方法差异,下文还会介绍其它方法进行处理

target对象与getTarget方法

在上一部分(“event对象与getEvent方法”)的介绍中,通过表格你可能已经发现

在IE中和其它兼容DOM的浏览器中,获取事件目标(target)的方法不同

在IE中,获取事件目标对象的方法为event.srcElement

而在其它兼容DOM的浏览器中,获取事件目标对象的方法却为event.target

getTarget方法正是为了处理这个差异而存在

在添加了EventUtil后,可以如下“重点语句”所示获取事件的目标(target)对象而无需担心上述差异导致的兼容问题

1 var btn=document.getElementById("myBtn");
2 var handler=function(event){
3    event=EventUtil.getEvent(event);
4    var target=EventUtil.getTarget(event); //重点语句
5 };
6 EventUtil.addHandler(btn,"click",handler); 

preventDefault方法

在其它兼容DOM的浏览器中,阻止特定事件的默认行为只需使用event对象自带的preventDefault( )方法,如下所示

1 var link=document.getElementById("myLink");
2 link.οnclick=function(event){
3    event.preventDefault(); //DOM0级或DOM2级阻止事件默认行为的方法
4 }

而在IE中,则需赋予event.returnValue的值为false才能阻止特定事件的默认行为

1 link.attachEvent("onclick",function(event){ 2 event.returnValue=false; //IE中阻止事件默认行为的方法 3 });

故在EventUtil中,存在一个preventDefault方法,用于统一上述差异

在添加了EventUtil后,可以如下“重点语句”所示阻止特定事件的默认行为而无需担心上述差异导致的兼容问题

1 var link=document.getElementById("myLink");
2 var handler=function(event){
3    event=EventUtil.getEvent(event);
4    EventUtil.preventDefault(event); //重点语句
5 };
6 EventUtil.addHandler(link,"click",handler);

stopPropagation方法

有时候,我们需要取消事件的进一步捕获或冒泡,即停止事件在DOM层次中传播

兼容DOM的浏览器可以通过使用event对象自带的stopPropagation( )方法做到这一点

1 var link=document.getElementById("myLink");
2 link.οnclick=function(event){
3    event.stopPropagation(); //DOM0级或DOM2级取消事件的进一步捕获或冒泡的方法
4 };

而在IE中,则需赋予event.cancelBubble的值为true

1 link.attachEvent("onclick",function(event){ 2 event.cancelBubble=true; //IE中取消事件的进一步冒泡的方法 3 });

EventUtil中的stopPropagation( )方法可以统一上述差异

在添加了EventUtil后,可以如下“重点语句”所示取消事件的进一步捕获或冒泡而无需担心差异导致的兼容问题

1 var link=document.getElementById("myLink");
2 var handler=function(event){
3    event=EventUtil.getEvent(event);
4    EventUtil.stopPropagation(event); //重点语句
5 };
6 EventUtil.addHandler(link,"click",handler);

相关元素与getRelatedTarget方法

mouseover与mouseout有“主目标(主元素)”与“相关元素”的概念

因为在发生mouseover或mouseout事件时,还会涉及到其它元素

这两个事件都会涉及把鼠指针从一个元素(相关元素)移到另一个元素(主目标)内

具体点说

对mouseover事件而言,事件的主目标是获得光标的元素,而相关元素是那个失去光标的元素

对mouseout事件而言,事件的主目标是失去光标的元素,而相关元素是那个获得光标的元素

DOM通过event对象的relatedTarget属性提供了相关元素的信息

但IE8及之前的版本不支持relatedTarget属性,不过提供了其它类似属性支持

在mouseover事件触发时,IE的formElement属性中保存了相关元素

在mouseout事件触发时,IE的toElement属性中保存了相关元素

EventUtil中的getRelatedTarget方法正是为了平衡这些差异而存在

在添加了EventUtil后,可以像下面示例“重点语句”一样使用getRelatedTarget方法

1 var div=document.getElementById("myDiv");
2 EventUtil.addHandler(div,"mouseout",function(event){
3    event=EventUtil.getEvent(event);
4    var target=EventUtil.getTarget(event);
5    var relatedTarget=EventUtil.getRelatedTarget(event); //重点语句
6    alert("鼠标离开了"+target.tagName+"元素而进入了"+relatedTarget.tagName+"元素");
7 });

getButton方法

我们知道,只有在鼠标主按钮被单击(或键盘回车键被按下、触摸屏被单点击中)时才会触发click事件

但对于mousedown和mouseup事件来说,鼠标上的任意按钮都可以触发它

有时,我们可能需要知道用户按下了哪个鼠标按钮

DOM的event.button属性可以做到这一点,这个属性可能有3个值

0表示主鼠标按钮(通常是左键)、1表示鼠标滚轮按钮、2表示鼠标右键

虽然IE的event对象也提供了button属性

但遗憾的是,IE的button属性与DOM的button属性有很大差异

而且不被其它浏览器支持,实用性很低,在此不予赘述

getButton方法的作用是,让所有浏览器的event.button表现与DOM相同

在添加了EventUtil后,可以像下面示例“重点语句”一样使用getButton方法而无需考虑IE中的差异

1 var div=document.getElementById("myDiv");
2 EventUtil.addHandler(div,"mousedown",function(event){ //监控按下div的是哪个按钮
3    event=EventUtil.getEvent(event);
4    alert(EventUtil.getButton(event));  //重点语句,弹出框显示按下哪个鼠标键的代号(0、1或2)
5 });
6 //同理,若事件是mouseup,则botton值表示释放的是哪个按钮

getWheelDelta方法

有时,为了让页面达到某些特殊效果,我们需要监视用户的鼠标滚轮操作

这一次,“与众不同”的是Firefox,而不是旧版本的IE

所有浏览器(包括IE6,除了Firefox)均支持鼠标滚轮事件mousewheel

而Firefox却是通过DOMMouseScroll事件实现类似功能

事件名的差异无法通过EventUtil改变

但关键是,这个事件表示鼠标滚轮滚动方向的方法,Firefox与其它浏览器也有差异

差异的本身已不是重点,重点是EventUtil的getWheelDelta方法可以很好的解决它们的差异

在添加了EventUtil后,可以像下面示例“重点语句”一样使用getWheelDelta方法而无需考虑FIrefox中的差异

1 function handleMouseWheel(event){
2    event=EventUtil.getEvent(event);
3    var delta=EventUtil.getWheelDelta(event);  //重点语句,delta是表示鼠标滚轮滚动方向的数值
4    alert(delta);
5 }
6 EventUtil.addHandler(document,"mousewheel",handleMouseWheel);      //非Firefox
7 EventUtil.addHandler(document,"DOMMouseScroll",handleMouseWheel);  //Firefox

多数情况下,我们只需关心如上例中通过getWheelDelta方法获得的delta数值的正负

当用户向前滚动鼠标滚轮时,delta的数值为正,反之为负

滚轮滚动越多,delta数值的绝对值越大,且均是120的倍数

getCharCode方法

在所有浏览器中,按下能够插入或删除的字符的按键都会触发keypress事件

但IE8-及Opera取得字符编码(ASCII码)的方式与其它浏览器是不同的

为了解决这一差异,在EventUtil中存在getCharCode方法

在添加了EventUtil后,可以像下面示例“重点语句”一样使用getCharCode方法来获取统一的字符编码

1 var textbox=document.getElementById("myText");
2 EventUtil.addHandler(textbox,"keypress",function(event){
3    event=EventUtil.getEvent(event);
4    alert(EventUtil.getCharCode(event)); //重点语句,弹出窗口中显示按下按键代表字符的ASCII码
5 });

转载于:https://www.cnblogs.com/dragonir/p/7805818.html

【前端】跨浏览器事件处理程序EventUtil.js个人注释及详解相关推荐

  1. element tabs 添加事件_JavaScript-跨浏览器事件处理程序-Web前端教程

    Web前端教程 事件对象属于内核对象,它包含一个使用计数,一个用于标识该事件是一个自动重置还是一个人工重置的布尔值,和另一个用于指定该事件处于已通知状态还是未通知状态的布尔值. 由上面所述,可见事件对 ...

  2. [万字长文]使用 React 重写学成在线前端项目 I 代码完整可运行,步骤有详解

    [万字长文]使用 React 重写学成在线前端项目 I 代码完整可运行,步骤有详解 准备工作 安装必备工具/库 nodejs React 脚手架 需要的 node 依赖包 分析需求 初始化项目 搭建框 ...

  3. 好程序员前端教程之JavaScript闭包和匿名函数的关系详解...

    好程序员前端教程之JavaScript闭包和匿名函数的关系详解 本文讲的是关于JavaScript闭包和匿名函数两者之间的关系,从匿名函数概念到立即执行函数,最后到闭包.下面一起来看看文章分析,希望你 ...

  4. nodejs 本地php服务器,node.js创建本地服务器详解

    本文主要和大家分享node.js创建本地服务器详解,简易上手node.js后,我们就可以在自己电脑上创建本地服务器了.希望能帮助到大家. 一.先上代码.//请求Node.js自带的http模块. va ...

  5. js打印三角形超详解

    js打印三角形超详解 j控制星星的总行数,i控制每行星星的打印个数 打印图形如下: (1) (2) //str=""用来存储星星// 理解步骤1:在一行输出6个星星如何操作,在循环 ...

  6. Android 事件分发机制分析及源码详解

    Android 事件分发机制分析及源码详解 文章目录 Android 事件分发机制分析及源码详解 事件的定义 事件分发序列模型 分发序列 分发模型 事件分发对象及相关方法 源码分析 事件分发总结 一般 ...

  7. Three.js - 摄像机的使用详解(透视投影摄像机、正交投影摄像机)

    一.两种摄像机的区别与比较 Three.js 库提供了两种不同的摄像机:透视投影摄像机和正交投影摄像机. 透视投影摄像机:这种摄像机的效果更贴近真实世界.也就是物体离摄像机越远,它们就会被渲染得越小. ...

  8. computed用发_Vue.js中computed使用详解

    这次给大家带来Vue.js中computed使用详解,Vue.js中computed使用的注意事项有哪些,下面就是实战案例,一起来看一下. JS属性: JavaScript有一个特性是Object.d ...

  9. Vue.js-Day01-PM【事件绑定(事件传参、事件对象、传参+获取事件对象)、样式处理操作(模板、事件、属性绑定)、Tab切换(原生js实现、Vue.js实现)、js中的this详解关键字】

    Vue.js实训[基础理论(5天)+项目实战(5天)]博客汇总表[详细笔记] 目   录 4.事件绑定 4.1.事件绑定(点击.双击.鼠标移动) 点击按钮-最简单的事件绑定(无参函数) 格式 点击按钮 ...

最新文章

  1. python读取excel-Python读取Excel表格
  2. USART中的SART_IT_RXNE,USART_IT_TC,USART_IT_TXE
  3. phoenix 开发API系列 目录
  4. 基于 Kyma 的企业级云原生应用的扩展案例分享
  5. scala集合转java_Java,Scala,Guava和Trove集合-它们可以容纳多少数据?
  6. 如何利用WGET覆写已存在的档案
  7. php百度坐标转腾讯坐标,PHP腾讯与百度坐标转换
  8. 利用支付宝和浙江图书馆网站免费获取知网文献(亲测可用)
  9. 台式计算机检测不到无线网卡,台式机检测不到无线网卡怎么办
  10. Oracle中文转拼音函数
  11. java门基础学习(五)
  12. MindMap学习使用
  13. 数据库中,DDL,DQL,DML,DCL是什么意思?
  14. 中铁汇达保险经纪保单计算个人理解
  15. 指标波动的原因很头疼?不妨试试“问诊”法!
  16. 求多个数的最小公倍数或最大公约数
  17. Ubuntu下校园网锐捷客户端的连接
  18. 【TA-霜狼_may-《百人计划》】图形4.5 DoF景深基础
  19. 自由谈:为什么使用 Linux
  20. 238 除自身以外数组的乘积(前后缀分解)

热门文章

  1. Excel-怎样实现行列转置
  2. PostgreSQL数据库设置远程连接
  3. Ruby版本管理(RVM)
  4. 内卷严重?加班多?给几条程序员都适用的建议
  5. 为什么美国互联网没有“运营”岗?
  6. Java虚拟机调用jni_JNI攻略之十一――启动虚拟机调用java类
  7. 转盘抽奖php,使用PHP实现转盘抽奖算法案例解析
  8. 什么是python中子类父类_零基础入门:python中子类继承父类的__init__方法实例
  9. word置顶_小鱼便签怎么设置置顶
  10. r语言 断轴 画图_R 绘图 – 函数曲线图 | 菜鸟教程