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

根据 W3C DOM 2 Events 描述,EventTarget 接口被所有支持 DOM 事件模型的节点(Node)实现。 该接口提供了 'addEventListener' 和 'removeEventListener' 方法,用来绑定或解绑一个 EventListeners 接口到一个 EventTarget。

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

DOM 2 事件模型允许 DOM 实现支持事件的多模块,如果有必要,事件模型允许附加新的事件模块。 为了共同使用性的目的,DOM 会定义一个包含低级别的,依赖设备的事件模块、一个 UI 逻辑事件模块和一个文档变化事件模块的 UI 事件模块。 第三方实现(比如浏览器厂商)在定义一个新类型事件的时候,事件名称一定不能使用大小写无关的 'DOM' 字符串作开头,该前缀是为未来的 DOM 事件模块保留的。

DOM 2 已经定义了一个 UI 事件类型模块和一个鼠标事件类型的模块,它们分别对应 UIEvent 和 MouseEvent 接口。 这两个接口提供了若干标准属性和方法,以获知事件发生时的一些信息。

关于 EventTarget 接口的详细信息,请参考 DOM 2 Events 。

关于 Event 接口的详细信息,请参考 DOM 2 Events 。

关于事件模块的详细信息,请参考 DOM 2 Events 。

问题描述

各浏览器对元素绑定、解绑事件监听器的方法,事件对象的获取,以及 Event 对象的实现上存在差异。

造成的影响

如果使用某浏览器特有的事件相关的属性及方法编写代码,则可能造成兼容性问题,导致代码报错,功能失效。

受影响的浏览器 所有浏览器    
问题分析 1. 只有 IE Opera 支持使用 'attachEvent' 和 'detachEvent' 方法绑定和解绑事件监听器

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

分析以下代码:

<button type="button">add event listener test</button> <button type="button">remove event listener test</button> <div></div> <script type="text/javascript"> var add = document.getElementById("add"), remove = document.getElementById("remove"), showMsgA = function(){showMsg("attachEvent")}, showMsgB = function(){showMsg("addEventListener")}; if(add.attachEvent){ add.attachEvent("onclick",showMsgA); remove.attachEvent("onclick",removeE); } if(add.addEventListener){ add.addEventListener("click",showMsgB,false); remove.addEventListener("click",removeE,false); } function removeE(){ if(add.detachEvent){ add.detachEvent("onclick",showMsgA); showMsg("detachEvent"); } if(add.removeEventListener){ add.removeEventListener("click",showMsgB,false); showMsg("removeEventListener"); } } function showMsg(method){ document.getElementById("info").innerHTML += ("support " + method + "<br />"); } </script>

依次点击 'add event listener test' >> 'remove event listener test' >> 'add event listener test',测试各浏览器对这些方法的支持,结果如下:

IE6 IE7 IE8  
Opera

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

 
Chrome Safari Firefox  

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

IE 不支持在捕获阶段触发事件监听器,'attachEvent' 方法没有提供参数说明是否响应在捕获阶段触发的事件; 'addEventListener' 和 'attachEvent' 都可以注册多个事件监听器; 在 Firefox Chrome Safari Opera 中给同一事件注册同一个事件监听器多次,重复注册的会被丢弃;而在 IE 中重复注册的事件监听器会被重复执行多次; 当给同一元素注册了多个事件监听器的时候,IE6 IE7 的事件监听器执行顺序是随机的,IE8 是倒序的,Firefox Chrome Safari Opera 是顺序的; 当元素注册的事件监听器中有非法的事件监听器时(非函数),在 IE Firefox 中会抛出异常,而在 Chrome Safari Opera 中则会忽略非法的事件监听器,继续执行其他的事件监听器。 2. 各浏览器获取事件对象的差异

DOM 2 Events 中规定使用事件监听器的第一个参数作为事件对象,而 IE Opera Chrome Safari 还支持通过 window.event 获取事件对象。

分析以下代码:

<button type="button">attachEvent</button> <button type="button">addEventListener</button> <button type="button">onClick</button> <br /> INFO : <div></div> <script type="text/javascript"> function $(id){return document.getElementById(id);} var attach = $("attach"), addE = $("addE"), byClick = $("byclick"); attach.attachEvent && attach.attachEvent("onclick", handler); addE.addEventListener && addE.addEventListener("click", handler, false); byClick.onclick = handler; function handler(){ var src = window === this ? window.event.srcElement : this, type = src.innerHTML; window.event && showMsg(window.event.type, type + " + window.event"); arguments[0] && showMsg(arguments[0].type, type + " + arguments[0]"); } function showMsg(type, msg){ $("info").innerHTML += (msg + "(type : " + type + ")<br />"); } </script>

以上代码组合不同的事件监听器绑定方式和事件对象获取方法,测试各浏览器的支持程度。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdxwgj.html