事件基本概念
事件類型:用來說明發(fā)生什么類型事件的字符串,即事件名。
事件目標(biāo):發(fā)生事件的對象。當(dāng)談?wù)撌录r,會同時指明類型和目標(biāo)。
事件處理程序:處理或響應(yīng)事件的函數(shù),即事件監(jiān)聽程序。
事件對象:與特定事件相關(guān)并且包含有關(guān)該事件詳細(xì)信息的對象。事件對象作為參數(shù)傳遞給事件處理程序(IE8之前的瀏覽器通過Event獲取事件對象)。
事件傳播:事件發(fā)生時,事件會由window發(fā)出,不斷經(jīng)過下一級節(jié)點直到目標(biāo)節(jié)點,到達目標(biāo)節(jié)點后,事件會按原路線返回window,事件從目標(biāo)節(jié)點返回window的過程就是事件傳播,又稱冒泡階段。在事件傳播階段可以通過事件對象阻止事件傳播。
事件捕獲: 事件發(fā)生時,事件會由window發(fā)出,不斷經(jīng)過下一級節(jié)點直到目標(biāo)節(jié)點,這一過程就是事件捕獲,又稱捕獲階段。在事件捕獲階段可以通過事件對象阻止事件捕獲。IE8之前的瀏覽器不支持事件捕獲。
常見事件類型
1.Window事件
發(fā)生在瀏覽器窗口上的事件,部分事件的事件類型會與文檔中的某些事件類型同名,包括文檔以及外部資源完全加載時觸發(fā)的load事件;瀏覽器窗口文檔跳轉(zhuǎn)到新文檔時觸發(fā)unload事件,該事件觸發(fā)時不影響文檔跳轉(zhuǎn);在文檔跳轉(zhuǎn)之前如果需要征得用戶同意,可以使用beforeunload事件;瀏覽器窗口加載文檔過程中出錯時觸發(fā)error事件;瀏覽器窗口尺寸改變時觸發(fā)resize事件,滾動條滾動時觸發(fā)scroll事件;瀏覽器窗口獲取焦點或者失去焦點時,分別觸發(fā)focus事件,blur事件;
2.DOM事件
主要有表單事件,鼠標(biāo)事件,鍵盤事件,文本事件,文檔加載事件。
表單事件包括提交表單時觸發(fā)submit事件;重置表單時觸發(fā)reset事件;表單元素內(nèi)容修改時觸發(fā)change事件;得到焦點,失去焦點時觸發(fā)focus事件,blur事件;表單元素的點擊時觸發(fā)click事件等;
鼠標(biāo)事件包括點擊鼠標(biāo)時觸發(fā)click事件;移動鼠標(biāo)時觸發(fā)mousemove事件;按下,釋放鼠標(biāo)按鍵時觸發(fā)mousedown事件,mouseup事件;點擊右鍵時觸發(fā)contextmenu事件,可以用來修改上下文菜單;連續(xù)點擊兩次鼠標(biāo)按鍵時觸發(fā)dblclick事件;鼠標(biāo)滑到元素上,離開元素時觸發(fā)mouseover事件,mouseup事件,IE中對應(yīng)mouseenter事件,mouseleave事件;
鍵盤事件包括按下,釋放按鍵時觸發(fā)的keydown事件,keyup事件;keydown事件與keyup事件之前會觸發(fā)keypress事件;
文本事件,使用webkit內(nèi)核的瀏覽器支持textInput事件,該事件在產(chǎn)生可打印字符時觸發(fā);
3.HTML5事件
主要是指HTML5標(biāo)準(zhǔn)化的事件以及新增的事件。
事件傳播
一個事件發(fā)生時,是事件先從文檔根節(jié)點流向事件目標(biāo),然后在事件目標(biāo)上觸發(fā)事件,然后再回溯到文檔根節(jié)點,即事件傳播有三個階段,從文檔根節(jié)點流向事件目標(biāo)是捕獲階段,到達事件目標(biāo)是目標(biāo)階段,然后從事件目標(biāo)到文檔根節(jié)點是冒泡階段(IE8之前的瀏覽器不支持捕獲階段,所以其事件傳播,只有冒泡階段)。完整流程如下圖。

這里有一個Demo形象的模擬了事件傳播過程。
事件代理
瀏覽器都支持冒泡階段,我們可以利用瀏覽器的冒泡機制,通過監(jiān)聽父級節(jié)點來實現(xiàn)監(jiān)聽子節(jié)點的功能,這就是事件代理的概念。
使用事件代理的好處:
1.減少事件綁定次數(shù),提高頁面性能;
2.可以監(jiān)聽動態(tài)變化的DOM結(jié)構(gòu),前提是父級節(jié)點不是動態(tài)變化的,子節(jié)點可以動態(tài)變化。
原理是在父級節(jié)點綁定相應(yīng)事件處理程序,當(dāng)對應(yīng)事件在子節(jié)點觸發(fā)時通過冒泡階段把事件傳遞到父節(jié)點,在父節(jié)點觸發(fā)事件處理程序,再根據(jù)事件對象的target屬性可以獲取到是哪個事件目標(biāo),然后就可以根據(jù)不同的事件目標(biāo),來實現(xiàn)不同的業(yè)務(wù)邏輯。
事件監(jiān)聽(綁定,注冊)
主要有以下方式來注冊事件處理程序:
1.通過設(shè)置事件目標(biāo)的事件屬性,這些事件屬性主要是由“on+事件名”組成。
例如:
document.getElementByTagName("a").onclick = function(){console.log("This is a click event");};
通過這種方式注冊事件處理程序,同一個事件目標(biāo)一次只能注冊一個事件處理程序。
2.通過設(shè)置標(biāo)簽屬性注冊事件處理程序。
例如:
<a onclick="console.log('This is a click event')"></a>
通過這種方式只需要把函數(shù)體賦值給事件屬性即可,同樣的這種方式一次也只能注冊一個事件處理程序。
3.支持標(biāo)準(zhǔn)事件模型的瀏覽器(IE8以及IE8之前的瀏覽器除外)中,事件目標(biāo)對象中都有一個addEventListener()方法,可以使用這個方法給事件目標(biāo)注冊事件處理程序。使用這個方法一次可以給事件目標(biāo)注冊多個不同的事件處理程序,使用不同的事件處理程序參數(shù)多次調(diào)用即可,觸發(fā)時根據(jù)注冊順序先后執(zhí)行事件處理程序。相同的事件處理程序參數(shù)多次調(diào)用這個方法注冊,也只能注冊一次。
這個方法的完整定義:
element.addEventListener(event, function, useCapture)
event 必傳參數(shù) 指定事件名
function 必傳參數(shù) 事件處理程序
userCapture 可選參數(shù) 默認(rèn)為false,指定事件處理程序在冒泡階段執(zhí)行;ture,指定事件處理程序在捕獲階段執(zhí)行
4.不支持標(biāo)準(zhǔn)事件模型的瀏覽器(IE8以及IE8之前的瀏覽器)中,事件目標(biāo)可以使用attachEvent()方法來注冊事件處理程序。相同的事件處理程序使用這個方法可以被注冊多次。
這個方法的完整定義:
element.attachEvent(event, function, useCapture)
event 必傳參數(shù) 指定 "on"+事件名
function 必傳參數(shù) 事件處理程序
由于IE8以及IE8之前瀏覽器不支持事件捕獲,所以這個方法只有兩個參數(shù)。
注意:IE9,IE10即支持
addEventListener()方法又支持attachEvent()方法來注冊事件處理程序,但是IE8,IE7,IE6,IE5瀏覽器只支持attachEvent()方法注冊事件處理程序。
事件調(diào)用順序
1.通過方式1,2注冊的事件處理程序優(yōu)先執(zhí)行。
2.通過方式3注冊的事件處理程序按照注冊順序執(zhí)行。
3.通過方式4注冊的事件處理程序執(zhí)行順序不定,(測試發(fā)現(xiàn)IE9,IE10按照注冊順序正序執(zhí)行,IE8按照注冊順序倒序執(zhí)行)。
事件解綁,注銷
通過方式1,2注冊的事件無法解綁。
通過方式3注冊的事件處理程序可以通過 removeEventListener()方法解綁, removeEventListener()方法有三個參數(shù),第一個參數(shù)與addEventListener()方法一樣,需要傳事件名;第二個參數(shù)需要傳 用addEventListener()方法注冊的事件處理程序函數(shù)名,即想要解綁addEventListener()方法注冊的事件處理程序,那么在注冊時必須用事先聲明好的函數(shù),不能用匿名函數(shù)注冊;第三個參數(shù)與addEventListener()方法的第三個參數(shù)一樣。
通過方式4注冊的事件處理程序可以通過detachEvent()方法解綁,detachEvent()方法參數(shù)與attachEvent()方法參數(shù)一樣,使用時和 removeEventListener()方法類似。
事件取消
1.取消發(fā)生該事件時瀏覽器的默認(rèn)操作
通過方式1,2注冊的事件處理程序,可以直接返回false來告訴瀏覽器不要執(zhí)行事件相關(guān)的默認(rèn)操作。
通過方式3注冊的事件處理程序,可以直接調(diào)用事件對象的preventDefault()方法來告訴瀏覽器不要執(zhí)行事件相關(guān)的默認(rèn)操作。
通過方式4注冊的事件處理程序,可以通過設(shè)置事件對象的returnValue屬性為false來告訴瀏覽器不要執(zhí)行事件相關(guān)的默認(rèn)操作。
2.取消事件傳播
通過方式1,2注冊的事件處理程序,不能取消事件傳播
通過方式3注冊的事件處理程序,可以直接調(diào)用事件對象的stopPropagation()方法來阻止事件傳播。
通過方式4注冊的事件處理程序,可以直接設(shè)置事件對象的cancelBubble屬性為true來阻止事件傳播。
自定義事件
對于支持標(biāo)準(zhǔn)事件模型的瀏覽器可以通過以下方式實現(xiàn)自定義事件
初始化事件類型
var event = new Event('myEvent');
或者
var event = document.createEvent('Event');
event.initEvent('myEvent',true,true);
綁定事件
element.addEventListener('myEvent',function(){});
解綁事件
element.removeEventListener('myEvent',funcName);
觸發(fā)事件
element.dispatchEvent(event);
針對支持標(biāo)準(zhǔn)事件模型的瀏覽器處理事件時大體流程相似,主要的區(qū)別有兩點,自定義事件需要初始化事件類型,以及使用dispatchEvent方法觸發(fā)事件
IE瀏覽器注冊自定義事件可以通過IE瀏覽器的私有的事件屬性propertychange實現(xiàn),具體參考漫談js自定義事件、DOM/偽DOM自定義事件
如果引用了jquery,使用自定義事件就比較簡單了
綁定事件
element.on("myEvent",function(){});
解綁事件
element.off("myEvent");
觸發(fā)事件
element.trigger("myEvent");
自定義事件與內(nèi)置事件的區(qū)別關(guān)注點不一樣,自定義事件關(guān)注的是執(zhí)行事件的標(biāo)簽,觸發(fā)時機由程序控制;而內(nèi)置事件關(guān)注的是觸發(fā)事件的標(biāo)簽,觸發(fā)時機由瀏覽器控制。自定義事件詳細(xì)可以參考 Introducing custom events
資料來源
1.js權(quán)威指南
2.http://blog.jobbole.com/52430/
3.http://www.admin10000.com/document/6089.html
4.http://learn.jquery.com/events/introduction-to-custom-events/