上次的 《JS面試題 跨瀏覽器的事件處理函數的綁定和解除綁定定》一文中提供的跨瀏覽器事件處理函數的綁定中缺失了對event對象的跨瀏覽器處理。這裡對它進行補完。
在相容DOM的瀏覽器中,無論使用DOM0級(element.onXXX=handler)還是DOM2級(element.addEventListener)來綁定事件處理函數,event對象都會作為事件處理函數的參數被傳入。然而在IE中,使用DOM0級方法綁定事件處理函數卻沒有將event對象當做參數傳入,而是作為window對象的一個屬性存在。因此,跨瀏覽器獲得一個事件對象需要如下的代碼
element.onclick = function (event){
event = event || window.event;
}
標準的event對象包含以下屬性及方法
屬性/方法 類型 讀/寫 說明
bubbles Boolean 唯讀 表明事件是否會冒泡
cancelable Boolean 唯讀 表明是否可以取消事件的預設行為
currentTarget Element 唯讀 即綁定該事件處理函數的元素,不一定是事件的目標元素,因為事件可以冒泡至綁定了相應事件的上層元素
eventPhase Integer 唯讀 呼叫事件處理常式的階段:1.捕獲階段2.處於目標3.冒泡階段
typeString 唯讀 事件類型
target Element 唯讀 事件的目標元素,例如點擊的dom中最深層次的元素
preventDefault Function 唯讀 取消事件的預設行為的方法。只有事件的cancelable為true時調用此方法才有效。
stopPropogation Function 唯讀 取消事件的進一步冒泡或捕獲。
而IE的事件對象包含如下屬性
屬性/方法 類型 讀/寫 說明
cancelBubble Boolean 讀/寫 預設值為false,將其設定為true就可以阻止事件冒泡。
returnValue Boolean 讀/寫 預設為true,將其設定為false就可以取消事件的預設行為,但沒有其他屬性可以說明是否有效。
typeString 唯讀 事件類型
srcElement Element 唯讀 事件的目標元素,與DOM事件中的target屬性一樣。
基於上述對比,需要相容處理的屬性和方法有event.target 和event.srcElement ,event.stopPropogation 和event.cancelBubble ,event.preventDefault 和event.returnValue 。可以提供一個跨瀏覽器的事件物件類型來處理相容問題。
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
};
這樣在LIZ.dom.addEventListener的處理中對向其註冊的事件處理函數傳入使用LIZ.dom.Event類型處理過的event對象,就可以在事件處理函數中使用跨瀏覽器的事件對象了。
1
addEventListener : function (element, type, handler){
2
3
var observer = this.getData(element, 'observer'),
4
proxyHandler = function (event){
5
observer.fire( new LIZ.dom.Event( event ) );
6
};
7
if( !observer || !(observer instanceof LIZ.patterns.Observer) ){
8
observer = new LIZ.patterns.Observer(element);
9
this.setData(element, 'observer', observer);
10
}
11
if( typeof observer[type] == 'undefined' ){
12
if( element.addEventListener ){
13
element.addEventListener(type, proxyHandler, false);
14
} else if ( element.attachEvent ){
15
element.attachEvent('on'+type, proxyHandler);
16
} else {
17
element['on'+type] = proxyHandler;
18
}
19
}
20
observer.addListener(type, handler);
21
}