本文主要談及問題:
- 關于編寫跨瀏覽器的事件處理函數和事件對象
關于編寫跨瀏覽器的事件處理函數和事件對象
-
為什么要編寫跨瀏覽器的事件處理函數和事件對象
近幾年來,個人對WINDOWS越來越沒愛。至于為什么無愛,我想原因有二:
- 轉投MAC陣營,覺得MAC比起WINDOWS對用戶太友好了
- 成為了一個前端工程師
講講第二點。網上一直流傳著一個段子:IE都有勇氣讓你把它設為默認瀏覽器,為什么你還連表白的勇氣都沒有。每每看到這個段子,心都有點痛,我想不僅是我,每個前端工程師都會有這樣的感覺。微軟在IE9之前,完全是think different ,make 更加 different。做出來的東西完全跟標準不一致。FE們為了兼容它沒少花心思。就拿事件模型來說,基本上最常用的模型有兩種:一種是DOM L2 EVENT MODEL.另外一種不用說,相信大家都知道,就是IE EVENT.所以我們就被逼著編寫跨瀏覽器的事件處理函數和事件對象。是不是覺得IE很作死,可是沒辦法啊,人家還占那么多份額,我們只能乖乖地兼容它。
-
怎么編寫跨瀏覽器的事件處理函數和事件對象
-
事件處理函數
-
DOM 事件處理函數(這里只談及DOM2)
DOM2級事件定義了兩種方法:- addEventListener(type,handler,useCapture); --添加事件處理函數
- removeEventListener(type,handler,useCapture); -- 刪除事件處理函數
這兩個方法都有三個參數:type為事件的類型,handler為事件處理程序的函數,userCapture(可選參數)為事件流類型,冒泡為false,捕獲為true,默認為false。
-
IE 事件處理函數
IE 事件定義了兩種方法:- 添加事件處理函數 :attachEvent("on"+type,handler);
- 刪除事件處理函數 :detachEvent("on"+type,handler);
這兩個方法都有兩個參數:第一個參數"on"+type是事件類型(如果在addEventListener的type為click,則此處應該為onclick),第二個參數handler為事件處理程序的函數。注意:IE8之前的瀏覽器只支持事件冒泡,不支持事件捕獲。
-
區別:
-
一個元素添加多個事件處理函數的執行順序:如果為一個元素添加多個事件處理函數,addEVentListener會按照添加的順序執行代碼。而attachEvent會按照添加順序的相反順序,如下:
var btn = document.getElementById('btn'); btn.addEventListener("click",function(){ alert("1"); }); btn.addEventListener("click",function(){ alert("2"); }); //以上代碼先輸出1,在輸出2 var btn = document.getElementById('btn'); btn.attachEvent("onclick"function(){ alert("1"); }) btn.attachEvent("onclick"function(){ alert("2"); }) //以上代碼先輸出2,再輸出1
-
事件處理程序的函數中的this:addEventListener的handler中的this指的是添加該事件處理函數的元素,而attachEvent的handler中的this指的是window對象。如下:
var bt = document.getElementById("bt"); bt.addEventListener("click",function(){ console.log(this === bt) }) //為true,this指添加事件處理函數的元素 var bt = document.getElementById("bt"); bt.attachEvent("onclick",function(){ console.log(this === window) }) //為true,this指window對象
-
-
跨瀏覽器事件處理函數 :
綜合上述的事件處理函數,我們可以寫出跨瀏覽器的事件處理函數,我們可以把它包含在一個對象里。如下:var eventForAllBrowsers = { addHandler :function(elem,type,handler){ if(elem.addEventListener){ elem.addEventListener(type,handler,false); } else if(elem.attachEvent){ elem.attachEvent("on"+type,handler); } else{ elem["on"+type] = handler; //加上對DOM 0 的支持 } }, removeHandler:function(elem,type,handler){ if(elem.removeEventListener){ elem.removeEventListener(type,handler,false) } else if(elem.detachEvent){ elem.detachEvent("on"+type,handler); } else { elem["on"+type] = null; } } }
-
-
事件對象
- DOM 事件對象
兼容DOM的瀏覽器會將一個event對象傳入到事件處理程序中。在函數內可以訪問event對象的屬性與方法。如下:
var bt = document.getElementById('bt');
bt.addEventListener("click",function(event){
alert(event.type)
})
event對象中包含的常用的屬性和方法:- preventDefault() --- 取消事件的默認行為。
- stopPropagation() --- 取消事件的進一步冒泡。
- type --- 被觸發的事件的類型。
- target --- 事件的目標。
- IE 事件對象
與兼容DOM的瀏覽器不同,要訪問IE的event對象分兩種情況:-
使用DOM 0 方法添加事件處理程序:在程序的函數內,用window.event去訪問event對象。如下:
var bt = document.getElementById('bt'); bt.onclick = function(){ var event = window.event; alert(event.type) }
-
使用IE 事件處理函數:將event對象傳入事件處理程序的函數內。如下:
var bt = document.getElementById('bt'); bt.attachEvent("onclick",function(event){ alert(event.type) })
-
-
event對象中包含的常用的屬性和方法:
- cacelBubble --- 默認值為false,將其設置為true就可以取消事件冒泡。
- returnValue --- 默認值為true,將其設置為false則可以取消事件的默認行為。
- srcElement --- 事件的目標。
- type --- 被觸發事件的類型。
- 跨瀏覽器的事件對象
通過檢查兼容DOM的瀏覽器的event對象的方法和屬性是否存在的方法去處理跨瀏覽器兼容性問題。把通用的事件對象的相關函數添加到eventForAllBrowsers上,代碼大致如下:
var eventForAllBrowsers = {
//省略上述的代碼
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;
}
}
}