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 相关文章推荐
一些Javascript的IE和Firefox(火狐)兼容性的问题总结及常用例子
May 21 Javascript
JavaScript模拟可展开、拖动与关闭的聊天窗口实例
May 12 Javascript
jQuery实现表格文本框淡入更改值后淡出效果
Sep 27 Javascript
纯JavaScript手写图片轮播代码
Oct 20 Javascript
基于jQuery实现的幻灯图片切换
Dec 02 Javascript
knockoutjs模板实现树形结构列表
Jul 31 Javascript
vue.js移动端app之上拉加载以及下拉刷新实战
Sep 11 Javascript
vue-router+vuex addRoutes实现路由动态加载及菜单动态加载
Sep 28 Javascript
原生js实现公告滚动效果
Jan 10 Javascript
Vue el-autocomplete远程搜索下拉框并实现自动填充功能(推荐)
Oct 25 Javascript
js数据类型转换与流程控制操作实例分析
Dec 18 Javascript
vue video和vue-video-player实现视频铺满教程
Oct 30 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
用PHP实现验证码功能
2006/10/09 PHP
一个用php3编写的简单计数器
2006/10/09 PHP
PHP学习 运算符与运算符优先级
2008/06/15 PHP
深入php define()函数以及defined()函数的用法详解
2013/06/05 PHP
WordPress主题中添加文章列表页页码导航的PHP代码实例
2015/12/22 PHP
php5.x禁用eval的操作方法
2018/10/19 PHP
Laravel框架源码解析之反射的使用详解
2020/05/14 PHP
IE6下通过a标签点击切换图片的问题
2010/11/14 Javascript
Jquery插件分享之气泡形提示控件grumble.js
2014/05/20 Javascript
Javascript中For In语句用法实例
2015/05/14 Javascript
使用three.js 画渐变的直线
2016/06/05 Javascript
Node.js 文件夹目录结构创建实例代码
2016/07/08 Javascript
vue.js表格组件开发的实例详解
2016/10/12 Javascript
javascript中Number的方法小结
2016/11/21 Javascript
Js apply方法详解
2017/02/16 Javascript
Linux CentOS系统下安装node.js与express的方法
2017/04/01 Javascript
深入探究node之Transform
2017/07/20 Javascript
详解在vue-cli项目中使用mockjs(请求数据删除数据)
2017/10/23 Javascript
小程序实现自定义导航栏适配完美版
2019/04/02 Javascript
[02:23]DOTA2英雄基础教程 幻影长矛手
2013/12/09 DOTA
Python正则表达式使用经典实例
2016/06/21 Python
Python django实现简单的邮件系统发送邮件功能
2017/07/14 Python
python 使用值来排序一个字典的方法
2018/11/16 Python
Python 数据可视化pyecharts的使用详解
2019/06/26 Python
利用python中集合的唯一性实现去重
2020/02/11 Python
python遍历路径破解表单的示例
2020/11/21 Python
英国时尚饰品和发饰购物网站:Claire’s
2017/07/04 全球购物
乌克兰珠宝大卖场:Zlato.ua
2020/09/27 全球购物
关于期中考试的反思
2014/02/02 职场文书
2014年教师业务学习材料
2014/05/12 职场文书
2014年人事科工作总结
2014/11/19 职场文书
寒暑假实习证明书模板
2014/11/29 职场文书
农民工工资承诺书大全
2015/05/04 职场文书
教师学习十八届五中全会精神心得体会
2016/01/05 职场文书
selenium.webdriver中add_argument方法常用参数表
2021/04/08 Python
python 远程执行命令的详细代码
2022/02/15 Python