事件(event)
- 事件就是 web 瀏覽器通知應(yīng)用程序發(fā)生了什么事情股耽。事件是可以被 javascript 偵測(cè)到的行為根盒。
- 事件類(lèi)型(event type)是一個(gè)用來(lái)說(shuō)明發(fā)生什么類(lèi)型事件的字符串。由于事件類(lèi)型只是一個(gè)字符串物蝙,因此實(shí)際上有時(shí)會(huì)稱(chēng)之為事件名字(event name)炎滞。
- 事件目標(biāo)(event target)是發(fā)生的事件或與之相關(guān)的對(duì)象。
- 事件處理程序(event handler)或事件監(jiān)聽(tīng)程序(event listener)是處理或響應(yīng)事件的函數(shù)诬乞。應(yīng)用程序通過(guò)指明事件類(lèi)型和事件目標(biāo)册赛,在 web 瀏覽器中注冊(cè)它們的事件處理程序函數(shù)。
- 事件對(duì)象(event object)是與特定事件相關(guān)且包含有關(guān)該事件詳細(xì)信息的對(duì)象震嫉。
- 事件傳播(event propagation)是瀏覽器決定哪個(gè)對(duì)象觸發(fā)其事件處理函數(shù)的過(guò)程森瘪。
事件類(lèi)型(event type)
- 傳統(tǒng)事件類(lèi)型
- 表單事件
- submit 事件:提交按鈕(`<input type="submit"/>`)被點(diǎn)擊。
- reset 事件:重置按鈕(`<input type="reset">`)被點(diǎn)擊责掏。
- focus 事件:元素獲得焦點(diǎn)。
- blur 事件:元素失去焦點(diǎn)湃望。
- change 事件:改變域的內(nèi)容换衬。
- window 事件
- load 事件:某個(gè)頁(yè)面或圖像被完成加載。
- unload 事件:用戶退出頁(yè)面证芭。
- beforeunload:在即將離開(kāi)當(dāng)前頁(yè)面(刷新或者關(guān)閉)是執(zhí)行瞳浦。
- error 事件:當(dāng)加載文檔或圖像時(shí)發(fā)生某個(gè)錯(cuò)誤。
- resize 事件:窗口或框架被調(diào)整尺寸废士。
- scroll 事件:元素滾動(dòng)條滾動(dòng)叫潦。
- 鼠標(biāo)事件
- mousemove 事件:鼠標(biāo)被移動(dòng)或拖動(dòng)鼠標(biāo)。
- mouseout 事件:鼠標(biāo)不再懸停到某個(gè)元素上官硝。
- mousedown 事件:鼠標(biāo)按下矗蕊。
- mouseup 事件:鼠標(biāo)釋放。
- click 事件:?jiǎn)螕羰髽?biāo)按鍵氢架。
- dblclick 事件:短時(shí)間連續(xù)兩次單擊(雙擊)鼠標(biāo)按鍵傻咖。
- 鍵盤(pán)事件
- keydown 事件:某個(gè)鍵被按下。
- keyup 事件:某個(gè)鍵被松開(kāi)岖研。
- keypress 事件:某個(gè)鍵被按下或按住卿操。
- DOM 事件
- HTML5 事件
HTML5及相關(guān)標(biāo)準(zhǔn)定義了大量的新的 web 應(yīng)用 api。
廣泛推廣的HTML5特性之一是加入用于播放音頻和視頻的<audio>
和<video>
元素。這些元素有著長(zhǎng)長(zhǎng)的事件列表害淤,他們觸發(fā)各種關(guān)于網(wǎng)絡(luò)事件扇雕、數(shù)據(jù)緩沖狀況和播放狀態(tài)的通知。
拖放事件:
- 觸摸屏和移動(dòng)設(shè)備事件
- 手勢(shì)事件 gesture
- gesturestart 事件:手勢(shì)生成窥摄。
- gesturechange 事件:手勢(shì)過(guò)程镶奉。
- gestureend 事件:手勢(shì)結(jié)束。
- 觸摸事件 touch
- touchstart 事件:手指觸摸屏幕溪王。
- touchmove 事件:手指移動(dòng)腮鞍。
- touchend 事件:手指離開(kāi)。
- 橫豎屏切換 orientation
- orientationchange 事件:豎屏旋轉(zhuǎn)到橫屏模式莹菱。
window 對(duì)象的 orientation 屬性能給出當(dāng)前方位移国,其值是 0,90道伟,180迹缀,-90。
注冊(cè)事件處理程序
- 設(shè)置 javascript 對(duì)象屬性為事件處理程序
事件處理程序?qū)傩缘拿钟?“on” 后面跟著事件名組成:onclick蜜徽、 onchange祝懂、 onload、 onmouseover 等拘鞋。
window.onload = funciton () {
var elt = document.getElementById("shipping_address");
elt.onsubmit = function () {
return validate(this);
}
}
- 設(shè)置 HTML 標(biāo)簽屬性為事件處理程序
設(shè)置的文檔元素事件處理程序?qū)傩裕╬roperty)也能換成對(duì)應(yīng) HTML 標(biāo)簽的屬性(attribute)砚蓬。
<button onclick="alert('Thank you')">點(diǎn)擊這里</button>
- addEventListener()
除 IE8 及之前版本外的所有瀏覽器都支持。
addEventListener() 接收三個(gè)參數(shù)盆色。第一個(gè)是要注冊(cè)處理程序的事件類(lèi)型(不包括 on )灰蛙;第二個(gè)參數(shù)是當(dāng)指定類(lèi)型的事件發(fā)生時(shí)應(yīng)該調(diào)用的函數(shù)。最后一個(gè)參數(shù)是布爾值隔躲。通常情況下摩梧,會(huì)給這個(gè)參數(shù)傳遞 false。如果相反傳遞了 true宣旱,那么函數(shù)將注冊(cè)為捕獲事件處理程序仅父,并在事件不同的調(diào)度階段調(diào)用。
var b = document.getElementById("mybutton");
b.addEventListener("click", function() { alert("thanks!")}, false);
document.removeEventListener("mousemove", handleMouseMove, true);
- attachEvent
IE9 之前的 IE 不支持 addEventListener() 和 removeEventListener()浑吟。
IE5 及以后版本定義了類(lèi)似的方法 attachEvent() 和 detachEvent()笙纤。
- addEventListener()、 removeEventListener() 和 attachEvent()组力、 detachEvent() 區(qū)別
- 因?yàn)?IE 事件模型不支持事件捕獲粪糙,所以 attachEvent() 和 detachEvent() 要求只有兩個(gè)參數(shù):事件類(lèi)型和處理程序函數(shù)。
- IE 方法的第一個(gè)參數(shù)使用了帶 “on” 前綴的事件處理程序?qū)傩悦尴睢6菦](méi)有前綴的事件類(lèi)型蓉冈。
- attachEvent() 允許相同的事件處理函數(shù)注冊(cè)多次城舞。當(dāng)特定的事件類(lèi)型發(fā)生時(shí),注冊(cè)函數(shù)的調(diào)用次數(shù)和注冊(cè)次數(shù)一樣寞酿。
- this的區(qū)別
addEventLisener:事件處理程序會(huì)在當(dāng)前對(duì)象的作用域運(yùn)行家夺,因此,事件處理程序的 this 就是當(dāng)前對(duì)象伐弹。
attachEvent:事件處理程序是在全局作用域下運(yùn)行因此 this 就是 window 拉馋。
var b = document.getElementById("mybutton");
var handler = function () {
alert("thanks");
};
if (b.addEventListener) {
b.addEventListener("click", handler, false);
} else if (b.attachEvent) {
b.attachEvent("onclick", handler);
}
移除事件的兼容寫(xiě)法:
var EventTools={
removeEventListener:function (element,eventName,listener) {
if(element.removeEventListener){
element.removeEventListener(eventName,listener,false);
}else if(element.detachEvent){
element.detachEvent("on"+eventName,listener);
}else{
element["on"+eventName]=null;
}
}
};
事件傳播
事件傳播的三個(gè)階段
- 捕獲
- 目標(biāo):正在執(zhí)行當(dāng)前對(duì)象的事件處理程序。
- 冒泡
事件捕獲和事件冒泡
-
事件冒泡
如果元素 A 嵌套在元素 B 中惨好,那么 A 被點(diǎn)擊不僅 A 的 onclick 事件會(huì)被觸發(fā)煌茴,B 的 onclick 也會(huì)被觸發(fā)。觸發(fā)的順序是“由內(nèi)而外” 日川。
- 取消事件冒泡:
window.event.cancelBubble = true;//IE
e.stopPropagation();
- 如何阻止事件冒泡和默認(rèn)事件蔓腐?
//阻止瀏覽器的默認(rèn)行為
window.event?window.event.returnValue = false : e.preventDefault();
//停止事件冒泡
window.event?window.event.cancelBubble = true : e.stopPropagation();
原生 JavaScript 中,return false;
只阻止默認(rèn)行為龄句,不阻止冒泡回论,jQuery 中的 return false;
既阻止默認(rèn)行為,又阻止冒泡分歇。
-
事件捕獲
和事件冒泡正好相反傀蓉,逐級(jí)向下傳播,觸發(fā)的順序是“由外而內(nèi)”
其他
事件代理/委托的原理以及優(yōu)缺點(diǎn)
- 原理:靠事件的冒泡機(jī)制來(lái)實(shí)現(xiàn)职抡。讓自己所觸發(fā)的事件由他的父元素代替執(zhí)行葬燎。
- 優(yōu)點(diǎn):可以大量節(jié)省內(nèi)存占用,減少事件注冊(cè)缚甩∑拙唬可以實(shí)現(xiàn)當(dāng)新增子對(duì)象時(shí)無(wú)需再次對(duì)其綁定事件,對(duì)于動(dòng)態(tài)內(nèi)容部分尤為合適蹄胰。
- 缺點(diǎn):事件代理的應(yīng)用常用應(yīng)該僅限上述需求下岳遥,如果把所有的事件都代理就可能出現(xiàn)事件誤判奕翔,即本不應(yīng)用觸發(fā)事件的被綁上了事件(有人把頁(yè)面里所有的時(shí)間都綁定到 document 用委托的裕寨,只是及其不智的做法)
實(shí)現(xiàn)事件代理,要求兼容瀏覽
// ============ 簡(jiǎn)單的事件委托
function delegateEvent(interfaceEle, selector, type, fn) {
if(interfaceEle.addEventListener){
interfaceEle.addEventListener(type, eventfn);
}else{
interfaceEle.attachEvent("on"+type, eventfn);
}
function eventfn(e){
var e = e || window.event;
var target = e.target || e.srcElement;
//如果目標(biāo)元素與選擇器匹配則執(zhí)行函數(shù)
if (matchSelector(target, selector)) {
if(fn) {
//將fn內(nèi)部的this指向target(在此之前this都是指向的綁定事件的元素即interfaceEle)
fn.call(target, e);
}
}
}
}
/**
* only support #id, tagName, .className
* and it's simple single, no combination
*/
//比較函數(shù):判斷事件的作用目標(biāo)是否與選擇器匹配派继;匹配則返回true
function matchSelector(ele, selector) {
// 如果選擇器為ID
if (selector.charAt(0) === "#") {
return ele.id === selector.slice(1);
}
//charAt(0),返回索引為0的字符
//slice(a宾袜,b),從已有的數(shù)組或字符串返回從索引從a處開(kāi)始,截取到索引b之前的子數(shù)組或子字符串驾窟;
//如果選擇器為Class
if (selector.charAt(0) === ".") {
return (" " + ele.className + " ").indexOf(" " + selector.slice(1) + " ") != -1;
}
// 如果選擇器為tagName
return ele.tagName.toLowerCase() === selector.toLowerCase();
}
//toLowerCase()將字符串轉(zhuǎn)換成小寫(xiě)
//調(diào)用
var odiv = document.getElementById("oDiv");
delegateEvent(odiv,"a","click",function(){
alert("1");
})
參考自:
javascript權(quán)威指南
1.事件委托的原理以及優(yōu)缺點(diǎn) 2. 手寫(xiě)原生js實(shí)現(xiàn)事件代理庆猫,并要求兼容瀏覽器