事件處理程序在應(yīng)用中是必不可少的,雖然現(xiàn)在很多框架都有自己實現(xiàn)事件處理方法,但是熟知原生才能讓我們應(yīng)對各種各樣的需求并且實現(xiàn)自己的想法
事件流
這個是很基本很基本的概念了
DOM2級事件規(guī)定的事件流包括三個階段:
①事件捕獲階段
②處于目標階段
③冒泡階段
并且明確要求捕獲階段不會涉及事件目標
事件處理程序
這里主要講DOM2級事件處理程序,HTML事件處理程序和DOM0級事件處理程序現(xiàn)在幾乎很少接觸,故跳過
DOM2級事件處理程序
addEventListener()
接收三個參數(shù):①要處理的事件名②事件處理程序③布爾值(true表示捕獲階段調(diào)用時間處理程序(建議),false表示冒泡階段)
removeEventListenser()
接收的參數(shù)與addEventListener一樣,需要注意的是,通過addEventListener()添加的匿名函數(shù)將無法通過removeEventListener()移除
IE事件處理程序
addEventListener在IE8及更早版本都不給予支持,但有類似的兩個方法:attachEvent()和detachEvent(),同樣接收事件處理程序名稱和事件處理程序函數(shù)作為參數(shù),默認在冒泡階段調(diào)用
注意:
①這里的時間處理程序名稱沒有on前綴
②這里的時間處理程序會在全局作用域中運行,故this等于window
跨瀏覽器的事件處理程序
var EventUtil = {
addHandler:function(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if(elment.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;
}
}
}
事件對象
事件對象包含著所有與時間有關(guān)的信息,包括導(dǎo)致事件的元素耘成、事件的類型以及其他與特定時間相關(guān)的信息.事件對象又分為DOM事件對象和IE事件對象,下面將分開總結(jié)
DOM中的事件對象
兼容DOM的瀏覽器會將一個event對象傳入到事件處理程序中,event對象包含與創(chuàng)建它的特定事件有關(guān)的屬性和方法,不同事件類型不一樣,不過所有事件都有下列共同的屬性和方法
- bubbles 布爾值 表明事件是否冒泡
- cancelable 布爾值 表明是否可以取消事件的默認行為
- currentTarget 節(jié)點 其事件處理程序當前正在處理事件的那個元素
- defaultPrevented 布爾值 是否被阻止了默認操作
- detail Integer 與事件相關(guān)的細節(jié)
- eventPhase Integer 調(diào)用事件處理程序的階段:1->捕獲 2->處于目標 3->冒泡
- preventDefault() 取消事件的默認行為
- stopImmediatePropagation() 取消事件的進一步捕獲或冒泡同時阻止任何事件處理程序被調(diào)用(DOM3)
- stopPropagation() 取消事件的進一步捕獲或冒泡
- target 節(jié)點 事件的目標
- trusted 布爾值 是否為瀏覽器生成的
- type 被觸發(fā)的事件的類型
- view 與事件關(guān)聯(lián)的抽象視圖
注意:在事件處理程序內(nèi)部,對象this始終等于currentTarget,即相應(yīng)事件的元素,而不一定是觸發(fā)事件的元素,而event.target則指向觸發(fā)事件的元素
IE中的事件對象
要訪問IE中的event對象的方式取決于指定事件處理程序的方法:
①使用DOM0級添加事件處理程序時,event對象作為window對象的一個屬性存在
②使用attachEvent()添加的事件處理程序,會有一次event傳入事件函數(shù)中
③通過HTML特性制定的事件處理程序,可以通過一個叫event的變量來訪問event對象
IE的event對象同樣包含與創(chuàng)建它的事件相關(guān)的屬性和方法,但所有事件對象都會包含下面所列的屬性和方法
- cancelBubble 布爾值 默認false,設(shè)置為true可以取消事件冒泡
- returnValue 布爾值 默認true,但將其設(shè)置為false可以取消事件的默認行為
- srcElement 事件的目標,與DOM中的target屬性相同
- type 被觸發(fā)的事件的類型
跨瀏覽器的事件對象
var EventUtil = {
addHandler:function(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if(elment.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;
}
},
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;
}
}
}
事件類型
UI事件
- load
當頁面完全加載后在window上觸發(fā),當圖像加載完畢時在img元素上觸發(fā)等
注意:對于新圖像元素,只要設(shè)置了src屬性就會開始下載,但script和link只有在把相關(guān)元素添加到文檔后才會開始下載
- unload
在文檔被完全卸載后觸發(fā),利用最多的情況是清除引用,以避免內(nèi)存泄漏
- resize
當瀏覽器窗口被調(diào)整到一個新的高度或?qū)挾葧r,就會觸發(fā)resize事件,建議在該事件的事件處理程序中不要加入大計算量的代碼,因為會被頻繁執(zhí)行,從而導(dǎo)致瀏覽器反應(yīng)變慢
- scroll事件
發(fā)生滾動時觸發(fā),雖然在window對象上發(fā)生,但它實際表示的是頁面中相應(yīng)元素的變化,通常配合scrollLeft和scrollTop來使用
焦點事件
- focus
- blur
鼠標與滾輪事件
鼠標事件
- click
- dblclick
- mousedown
- mouseup
- mouseenter 在鼠標從元素外部首次移動到元素范圍之內(nèi)觸發(fā)
- mouseleave 在位于元素上方的鼠標光標移動到元素范圍之外時觸發(fā)
- mousemove 當鼠標指針在元素內(nèi)部移動時重復(fù)地觸發(fā)
- mouseout 當鼠標指針位于一個元素上方,然后用戶將其移入另一個元素時觸發(fā),又移入的另一個元素可能位于前一個元素的外部,也可能是這個元素的子元素
- mouseover 在鼠標指針位于一個元素外部,然后用戶將其首次移入另一個元素邊界之內(nèi)觸發(fā)
- mousewheel 當用戶通過鼠標滾輪與頁面交互薇溃、在垂直方向上滾動頁面都會觸發(fā)mousewheel事件
注意 除了mouseenter和mouseleave之外,所有鼠標事件都會冒泡
鼠標事件event特有屬性
- 客戶區(qū)坐標位置:
通過event.clientX和event.clientY來獲取鼠標光標距離視口的位置- 頁面坐標位置:
通過event.pageX和event.pageY來獲取鼠標光標距離頁面的位置- 屏幕坐標位置
通過event.screenX和event.screenY來獲取鼠標光標距離屏幕的位置- 修改鍵
鼠標可能會配合修改鍵使用,可以通過event.shiftKey,event.ctrlKey,event.altKey,event.metaKey的布爾值來獲知對應(yīng)的修改鍵是否按下了,從而給予正確的反饋事件- 相關(guān)元素
在發(fā)生mouseover和mouseout事件時,會涉及到更多的元素
①mouseover: 主目標是獲得光標的元素,相關(guān)元素是失去光標的元素
②mouseout: 主目標是失去光標的元素,相關(guān)元素是獲得光標的元素
DOM中,event.relatedTarget表示相關(guān)元素
IE8之前,前者用event.fromElement,后者用event.toElement來表示相關(guān)元素- 鼠標按鈕
對于mousedown和mouseup事件,其event對象存在一個button屬性,表示按下或釋放的按鈕,在DOM中,button屬性有以下值
0表示主鼠標按鈕
1表示中間按鈕
2表示次鼠標按鈕
在IE8及之前版本中也提供button屬性,不過屬性值與DOM有很大差異
這里有跨瀏覽器方案:
var EventUtil = {
//省略了其他代碼
getButton:function(event){
if(document.implementation.hasFeature("MouseEvents","2.0")){
return event.button
}else{
switch(event.button){
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 2:
case 6:
return 2;
case 4:
return 1;
}
}
},
//省略了其他代碼
};
鼠標滾輪事件
mousewheel的event對象除包含鼠標事件的所有標準信息外,還包含一個特殊的wheelDelta屬性(IE,Opera,Chrome,Safari), detail屬性(Firefox)
在wheelDelta
向前滾動:wheelDelta是120的倍數(shù)
向后滾動:wheelDelta是-120的倍數(shù)
在detail
向前滾動:detail的值是3的倍數(shù)
前后滾動:detail的值是-3的倍數(shù)
此處有跨瀏覽器方案:
var EventUtil = { //省略了其他代碼 getWheelDelta:function(event){ if(event.wheelDelta){ return(client.engine.opera&&client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta); }else{ return -event.detail * 40; } } }
鍵盤與文本事件
有三個鍵盤事件和一個文本事件
- keydown: 當用戶按下鍵盤上任意鍵時觸發(fā),按住不放則連續(xù)觸發(fā)
- keypress: 當用戶按下鍵盤上字符鍵時觸發(fā),按住不放則連續(xù)觸發(fā)
(Safari3.1之前的版本在按下非字符鍵時也會觸發(fā) - keyup: 當用戶釋放鍵盤上的鍵時觸發(fā)
- textInput: 在文本插入文本框前會觸發(fā)textInput事件,用意是將文本顯示給用戶之前更容易攔截文本
鍵盤事件event特有屬性
- 鍵碼
在發(fā)生keydown和keyup事件時,event對象的keyCode屬性會包含一個代碼與對應(yīng)的按鍵對應(yīng)- 字符編碼
發(fā)生keypress事件意味著按下的鍵會影響到屏幕中文本的顯示,因此在所有瀏覽器中,按下能夠插入或刪除字符的鍵都會觸發(fā)keypress事件
變動事件
- DOMSubtreeModified:在DOM結(jié)構(gòu)中發(fā)生任何變化時觸發(fā)
- DOMNodeInserted:在一個節(jié)點作為子節(jié)點被插入另一個節(jié)點時觸發(fā)
- DOMNodeRemoved: 在節(jié)點從其父節(jié)點中被移除時觸發(fā)
- DOMNodeInsertedIntoDocument:在一個節(jié)點被直接插入文檔或通過子樹間插入文檔之后觸發(fā)
- DOMNodeRedmovedFromDocument:同理
- DOMAttrModified:在特征被修改之后觸發(fā)
- DOMCharacterDataModified:在文本節(jié)點的值發(fā)生變化時觸發(fā)
HTML5事件
- contextmenu:單機鼠標右擊事件
- beforeunload:在瀏覽器卸載頁面之前觸發(fā)
- DOMContentLoaded:在頁面中的一切都加載完畢時觸發(fā),在形成完整的DOM樹之后就會觸發(fā)县钥,不理會圖像慷吊、js文件等資源是否下載完畢
- readystatechange
這個事件的目的時提供與文檔或元素的加載狀態(tài)有關(guān)的信息,支持此事件的每個對象都有一個readyState屬性 - pageshow和pagehide事件(Firfox opera)
- hashchange:在URL的參數(shù)列表發(fā)生改變時觸發(fā)
設(shè)備事件(略)
觸摸與手勢事件
觸摸事件
- touchstart:當手指觸摸屏幕時觸發(fā)
- touchumove:當手指在屏幕上滑動時連續(xù)地觸發(fā)
- touchend:當手指從屏幕上移開時觸發(fā)
- touchcancel:當系統(tǒng)停止跟蹤觸摸時觸發(fā)
除了常見的DOM屬性外描焰,觸摸事件還包含下列三個用于跟蹤觸摸的屬性:
(1)touches:表示當前跟蹤的觸摸操作的Touch對象的數(shù)組
(2)targetTouchs:特定與事件目標的Touch對象的數(shù)組
(3)changeTouched:表示自上次觸摸以來發(fā)生了什么變化的Touch對象的數(shù)組
手勢事件
- gesturestart:當一個手指已經(jīng)按在屏幕上而另一個手指又觸摸屏幕時觸發(fā)
- gesturechange:當觸摸屏幕的任何一個手指的位置發(fā)生變化時觸發(fā)
- gestureend:但任何一個手指從屏幕上面移開時觸發(fā)咐容。
注意:在一個元素上設(shè)置事件處理程序,意味著兩個手指必須同時位于該元素的范圍之內(nèi)滋捶,才能觸發(fā)手勢事件(這個元素就是目標)痛悯,由于這些事件冒泡,所以將事件處理程序放在文檔上也可以處理所有手勢事件重窟,此時事件的目標就是兩個手指都位于其范圍 內(nèi)的那個元素载萌。
特殊屬性: - rotation:表示手指變化引起的旋轉(zhuǎn)角度,負值表示逆時針旋轉(zhuǎn)
- scale:表示兩個手指尖距離的變化情況巡扇,這個值從1開始扭仁,并隨距離拉大而增長,隨距離縮小而減小
內(nèi)存和性能
事件委托
事件委托利用了事件冒泡厅翔,只指定一個事件處理程序乖坠,就可以管理某一類型的所有事件
EventUtil.addHandler(document,'click',function(event){
event = EventUtil.getTarget(event);
switch(target.id){
case "dosomething":
handleDosomething()
break;
case "goSomewhere":
handleGosomgwhere()
break;
}
});
事件委托的優(yōu)點:
- document對象很快就可以訪問,而且在頁面生命周期的任何時點上為它添加事件處理程序刀闷。換句話說熊泵,只要可點擊的元素呈現(xiàn)在頁面上,就可以立刻具備適當?shù)墓δ堋?/li>
- 在頁面中設(shè)置事件處理程序所需的時間更少甸昏,只添加一個事件處理程序所需的DOM引用更少顽分,所花的時間也更少。
- 整個頁面占用的內(nèi)存空間更少施蜜,能夠提升整體性能
模擬事件
DOM中的事件模擬
- ①document.createEvent()創(chuàng)建一個event對象卒蘸,可接受一個參數(shù),表示要創(chuàng)建的事件類型的字符串(UIEvetnts,MouseEvents,MutationEvents,HTMLEvents)
- ②創(chuàng)建的event對象都對應(yīng)有一個特殊的初始化方法翻默,傳入適當?shù)臄?shù)據(jù)可以初始化該evnet對象
- ③在DOM節(jié)點上使用dispatchEvent()方法觸發(fā)這個事件
自定義事件
自定義事件不是由DOM原生觸發(fā)的額缸沃,它的目的是讓開發(fā)人員創(chuàng)建自己的事件。
- ①調(diào)用document.createEvent('CustomEvent')創(chuàng)建一個自定義事件對象修械,有一個名為initCustomEvent()的方法接收以下4個參數(shù):
- type(字符串):觸發(fā)的事件類型
- bubbles(布爾值):表示時間是否應(yīng)該冒泡
- cancelable(布爾值):表示事件是否可以取消
- detaitl(對象):任意值趾牧,保存在event對象的detail屬性中
- ②在對應(yīng)節(jié)點上綁定該事件
- ③使用dispatchEvent(event)事件觸發(fā)。
此處跳過對IE的事件模擬肯污。