DOM 中的事件处理介绍


Posted in Javascript onJanuary 18, 2012

该接口提供了 'addEventListener' 和 'removeEventListener' 方法,用来绑定或解绑一个 EventListeners 接口到一个 EventTarget。

DOM 2 Events 中定义了 Event 接口,用来提供事件的上下文信息,它提供了若干标准属性和方法。 实现 Event 接口的对象一般作为第一个参数传入事件处理函数,以用来提供当前事件相关的一些信息。

事件注册
根据 DOM 2 Events 中描述,节点使用 'addEventListener' 和 'removeEventListener' 方法绑定和解绑事件监听器,但 IE6 IE7 IE8 不支持这两个方法, 而使用 'attachEvent' 和 'detachEvent' 方法作为替代方案,Opera 两类方法都支持。Chrome Safari Firefox 只支持标准方法。

为了解决浏览器兼容问题,可以自定义函数来解决。例如:

var EventUtil = { 
addHandler: function (element, type, handler) { 
if (element.addEventListener) { 
element.addEventListener(type, handler, false); 
} else if (element.attachEvent) { 
element.attachEvent("on" + type, handler); 
} else { 
element["on" + type] = handler; 
} 
}, 
removeHandler: function (element, type, handler) { 
if (element.removeEventListener) { 
element.removeEventListener(type, handler, false); 
} else if (element.detachEvent) { 
element.detachEvent("on" + type, handler); 
} else { 
element["on" + type] = null; 
} 
} 
};

关于 'addEventListener' 和 'attachEvent' 有几点需要注意:

IE 不支持在捕获阶段触发事件监听器,'attachEvent' 方法没有提供参数说明是否响应在捕获阶段触发的事件;
'addEventListener' 和 'attachEvent' 都可以注册多个事件监听器;
在 Firefox Chrome Safari Opera 中给同一事件注册同一个事件监听器多次,重复注册的会被丢弃;而在 IE 中重复注册的事件监听器会被重复执行多次;
当给同一元素注册了多个事件监听器的时候,IE6 IE7 的事件监听器执行顺序是随机的,IE8 是倒序的,Firefox Chrome Safari Opera 是顺序的;
当元素注册的事件监听器中有非法的事件监听器时(非函数),在 IE Firefox 中会抛出异常,而在 Chrome Safari Opera 中则会忽略非法的事件监听器,继续执行其他的事件监听器。
事件对象
在ie中,事件对象是作为一个全局变量来保存和维护的。 所有的浏览器事件,不管是用户触发的,还是其他事件, 都会更新window.event 对象。 所以在代码中,只要轻松调用 window.event 就可以轻松获取 事件对象, 再 event.srcElement 就可以取得触发事件的元素进行进一步处理。

对于标准的 DOM 处理来说, 事件对象却不是全局对象,一般情况下,是现场发生,现场使用,把事件对象自动传递给对应的事件处理函数。 在代码中,函数的第一个参数就是事件对象了。

为了解决兼容性问题,通常在代码中如下处理:

function handler(e){ 
e = e || window.event; 
}

需要注意的是,使用 <button id="btn" onclick="foo()">按钮1</button> 进行事件注册,标准方式下却不能在事件处理方法中取得事件对象。

原因是 onclick="foo()" 就是直接执行了, foo() 函数,没有任何参数传递给 foo 函数。

有两个办法解决这个问题。

第一,将注册的方法修改为 <button id="btn" onclick="foo(event)">按钮</button>,注意,这里的 event 不是形参,而是实参,必须名为 event。这样 foo 函数就可以得到事件参数了。

第二,不修改注册的代码,在事件处理方法上进行处理。关键在于此时实际上存在事件对象,只不过没有传递给 foo 函数罢了,我们可以找到调用 foo 函数的那个函数,当然这是一个系统函数,没有关系,通过 foo.caller 可以取得当前调用 foo 函数的函数,这个函数的第一个参数就是事件对象,所以,我们可以这样取得这个事件对象了。foo.caller.arguments[0]。

注意:

只有在使用 attachEvent 方法注册事件监听器的时候,IE 才支持使用事件监听器传入的第一个参数作为事件对象的方式;
Chrome Safari Opera 两种获取事件对象的方式都支持;
Firefox 只支持获取事件对象的标准方式。
事件对象的属性
IE 对事件对象的标准属性和方法支持有限,针对大部分属性和方法,IE 都提供了一套替代非标准的替代方案; 而 Firefox Chrome Safari Opera 除了全面支持事件对象的标准属性和方法外,还在不同程度上支持了 IE 提供的非标准替代方案。

使用特性判断使用与标准对应的非标准方法及属性

target

srcElement

preventDefault()

 returnValue

stopPropagation()

cancelBubble

relatedTarget

fromElement toElement

例如:

getEvent: function (event) { 
return event ? event : window.event; 
}, 
getTarget: function (event) { 
return event.target || event.srcElement; 
}, 
preventDefault: function (event) { 
if (event.preventDefault) { 
event.preventDefault(); 
} else { 
event.returnValue = false; 
} 
}, 
stopPropagation: function (event) { 
if (event.stopPropagation) { 
event.stopPropagation(); 
} else { 
event.cancelBubble = true; 
} 
}

参考资料:

SD9011: 事件模型在各浏览器中存在差异

Javascript 相关文章推荐
AngularJs  unit-testing(单元测试)详解
Sep 02 Javascript
微信小程序 WebSocket详解及应用
Jan 21 Javascript
vue.js 1.x与2.0中js实时监听input值的变化
Mar 15 Javascript
vue项目常用组件和框架结构介绍
Dec 24 Javascript
如何更好的编写js async函数
May 13 Javascript
详解webpack的proxyTable无效的解决方案
Jun 15 Javascript
vue中使用cookies和crypto-js实现记住密码和加密的方法
Oct 18 Javascript
详解axios中封装使用、拦截特定请求、判断所有请求加载完毕)
Apr 09 Javascript
js计时事件实现圆形时钟
Mar 25 Javascript
three.js利用gpu选取物体并计算交点位置的方法示例
Nov 25 Javascript
vue中el-input绑定键盘按键(按键修饰符)
Jul 22 Javascript
JavaScript 监听组合按键思路及代码实现
Jul 28 Javascript
深入理解JavaScript系列(13) This? Yes,this!
Jan 18 #Javascript
JavaScript中常用的运算符小结
Jan 18 #Javascript
jQuery LigerUI 使用教程表格篇(1)
Jan 18 #Javascript
jQuery LigerUI 使用教程入门篇
Jan 18 #Javascript
c#和Javascript操作同一json对象的实现代码
Jan 17 #Javascript
深入理解JavaScript系列(12) 变量对象(Variable Object)
Jan 16 #Javascript
Prototype源码浅析 Enumerable部分之each方法
Jan 16 #Javascript
You might like
967 个函式
2006/10/09 PHP
function.inc.php超越php
2006/12/09 PHP
PHP使用Alexa API获取网站的Alexa排名例子
2014/06/12 PHP
php控制文件下载速度的方法
2015/03/24 PHP
关于laravel后台模板laravel-admin select框的使用详解
2019/10/03 PHP
jquery 获取自定义属性(attr和prop)的实现代码
2012/06/27 Javascript
js判断60秒以及倒计时示例代码
2014/01/24 Javascript
node.js超时timeout详解
2014/11/26 Javascript
AngularJS中取消对HTML片段转义的方法例子
2015/01/04 Javascript
jQuery实现“扫码阅读”功能
2015/01/21 Javascript
jQuery使用removeClass方法删除元素指定Class的方法
2015/03/26 Javascript
js中跨域方法原理详解
2015/07/19 Javascript
jQuery实现hover合成事件的方法
2015/08/06 Javascript
js oncontextmenu事件使用详解
2017/03/25 Javascript
JavaScript脚本语言是什么_动力节点Java学院整理
2017/06/26 Javascript
AngularJS实现的获取焦点及失去焦点时的表单验证功能示例
2017/10/25 Javascript
JavaScript中为事件指定处理程序的五种方式分析
2018/07/27 Javascript
微信小程序滑动选择器的实现代码
2018/08/10 Javascript
在小程序中使用canvas的方法示例
2018/09/17 Javascript
在JavaScript中实现链式调用的实现
2019/12/24 Javascript
微信小程序实现菜单左右联动
2020/05/19 Javascript
[00:35]DOTA2上海特级锦标赛 EG战队宣传片
2016/03/04 DOTA
[01:09:40]Newbee vs Pain 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[01:42]DOTA2 – 虚无之灵
2019/08/25 DOTA
python中实现字符串翻转的方法
2018/07/11 Python
python根据txt文本批量创建文件夹
2020/12/08 Python
python3 requests库实现多图片爬取教程
2019/12/18 Python
将pytorch转成longtensor的简单方法
2020/02/18 Python
澳大利亚网上玩具商店:Mr Toys Toyworld
2018/03/25 全球购物
俄罗斯香水和化妆品在线商店:Aroma-butik
2020/02/28 全球购物
销售主管岗位职责范本
2014/02/14 职场文书
大学班级计划书
2014/04/29 职场文书
大班幼儿评语大全
2014/04/30 职场文书
应届生求职信
2014/05/31 职场文书
个人债务授权委托书
2014/10/17 职场文书
MongoDB 常用的crud操作语句
2021/06/20 MongoDB