JS 跨浏览器的dom事件封装

 

原文地址: JS 跨浏览器的dom事件封装

上次的 《JS面试题 跨浏览器的事件处理函数的绑定和解绑定》一文中提供的跨浏览器事件处理函数的绑定中缺失了对event对象的跨浏览器处理。这里对它进行补完。

在兼容DOM的浏览器中,无论使用DOM0级(element.onXXX=handler)还是DOM2级(element.addEventListener)来绑定事件处理函数,event对象都会作为事件处理函数的参数被传入。然而在IE中,使用DOM0级方法绑定事件处理函数却没有将event对象当做参数传入,而是作为window对象的一个属性存在。因此,跨浏览器获得一个事件对象需要如下的代码

1 element.onclick = function (event){
2     event = event || window.event;
3 }

标准的event对象包含以下属性及方法

属性/方法 类型 读写 说明
bubbles Boolean 只读 表明事件是否会冒泡
cancelable Boolean 只读 表明是否可以取消事件的默认行为
currentTarget Element 只读 即绑定该事件处理函数的元素,不一定是事件的目标元素,因为事件可以冒泡至绑定了相应事件的上层元素
eventPhase Integer 只读 调用事件处理程序的阶段:1.捕获阶段 2.处于目标 3.冒泡阶段
type String 只读 事件类型
target Element 只读 事件的目标元素,例如点击的dom中最深层次的元素
preventDefault Function 只读 取消事件的默认行为的方法。只有事件的cancelable为true时调用此方法才有效。
stopPropogation Function 只读 取消事件的进一步冒泡或捕获。

而IE的事件对象包含如下属性

属性/方法 类型 读写 说明
cancelBubble Boolean 读写 默认值为false,将其设置为true就可以阻止事件冒泡。
returnValue Boolean 读写 默认为true,将其设置为false就可以取消事件的默认行为,但没有其他属性可以说明是否有效。
type String 只读 事件类型
srcElement Element 只读 事件的目标元素,与DOM事件中的target属性一样。

基于上述对比,需要兼容处理的属性和方法有 event.target 和 event.srcElement ,event.stopPropogation 和 event.cancelBubble ,event.preventDefault 和 event.returnValue 。可以提供一个跨浏览器的事件对象类型来处理兼容问题。可以提供一个方法来简单的处理event的兼容性。使用之前所说的创建一个跨浏览器的事件对象类型的话存在很多弊端,一方面创建了新的对象消耗过大,一方面要使用其它事件特有的值还需要再调用方法获取原事件对象,这一方法创建了闭包会造成一些内存消耗。

1 LIZ.dom.Event = function ( event ){
2     event = event || window.event;
3     this.type = event.type;
4     this.target = event.target || event.srcElement;
5  
6     this.preventDefault = function (){
7         if ( event.preventDefault ){
8             event.preventDefault();
9         else {
10             event.returnValue = false;
11         }
12     };
13  
14     this.stopPropogation = function (){
15         if ( event.stopPropogation ){
16             event.stopPropogation();
17         else {
18             event.cancelBubble = true;
19         }
20     };
21  
22     //为提供一点灵活性,此处提供一个getEvent方法返回真正的event对象
23     this.getEvent = function (){
24         return event;
25     };
26  
27     return this;
28 };
1 /**
2 * 在LIZ.util中创建一个处理event兼容性的方法
3 * 只需要对IE的event对象进行兼容处理,向标准靠拢
4 * 给IE的event对象添加其本身不具备的标准的属性和方法
5 */
6 LIZ.util.compatibleEvent = function ( event ){
7     event = event || window.event;
8  
9     iftypeof event.target === 'undefined' ){
10         event.target = event.srcElement;
11     }
12  
13     iftypeof event.stopPropogation !== 'function' ){
14         event.stopPropogation = function (){
15             this.cancelBubble = true;
16         };
17     }
18  
19     iftypeof event.preventDefault !== 'function' ){
20         event.preventDefault = function (){
21             this.returnValue = false;
22         }
23     }
24  
25     return event;
26 };

虽然IE中的event对象与标准的event对象还有很多不一致的接口(属性,方法),但是不是每个事件处理函数都会用到所有的属性和方法,如果在compatibleEvent方法中做更多的兼容处理就有可能不会被用到而消耗了不必要的内存,所以只是提供几个简单的兼容是更好的选择。

这样在LIZ.dom.addEventListener的处理中对向其注册的事件处理函数传入使用LIZ.dom.Event类型LIZ.util.compatibleEvent方法处理过的event对象,就可以在事件处理函数中使用跨浏览器的事件对象了。

1 addEventListener : function (element, type, handler){
2     var observer = this.getData(element, 'observer'),
3     proxyHandler = function (event){
4         observer.fire( LIZ.util.compatibleEvent( event ) );
5     };
6     if( !observer || !(observer instanceof LIZ.patterns.Observer) ){
7         observer = new LIZ.patterns.Observer(element);
8         this.setData(element, 'observer', observer);
9     }
10     iftypeof observer[type] == 'undefined' ){
11         if( element.addEventListener ){
12             element.addEventListener(type, proxyHandler, false);
13         else if ( element.attachEvent ){
14             element.attachEvent('on'+type, proxyHandler);
15         else {
16             element['on'+type] = proxyHandler;
17         }
18     }
19     observer.addListener(type, handler);
20 }

 

本博客文章由LiZn创作或分享,以创作公用CC 姓名标示-非商业性-相同方式分享 3.0 Unported 授权条款共享。 
希望本文能够对你有所帮助,欢迎留言讨论,如果你喜欢本站文章,可以使用该 RSS订阅地址来订阅本站。

 

你可能感兴趣的:(JavaScript,面试题)