"事件是一種異步編程的實(shí)現(xiàn)方式,本質(zhì)上是程序各個(gè)組成部分之間的通信。
1、EventTarget接口
dom的事件操作(監(jiān)聽和觸發(fā)),都定義在這個(gè)接口上。
該接口有三個(gè)方法:
addEventListener:綁定事件的監(jiān)聽函數(shù)
removeEventListener:移除事件的監(jiān)聽函數(shù)
dispatchEvent:觸發(fā)事件
1.1、addEventListener
格式:target.addEventListener(type,listener[,useCapture]);
"useCapture":監(jiān)聽函數(shù)是否在捕獲階段觸發(fā)。默認(rèn)為false(監(jiān)聽函數(shù)在冒泡階段觸發(fā))。
addEventListener方法可以給當(dāng)前對(duì)象的同一事件,添加多個(gè)監(jiān)聽函數(shù),執(zhí)行順序是先添加先執(zhí)行。但是如果監(jiān)聽函數(shù)也是同一個(gè),則只執(zhí)行一次。

1.2、removeEventListener()
removeEventListener方法用來移除addEventListener方法添加的事件監(jiān)聽函數(shù)。
1.3、dispatchEvent()
當(dāng)前節(jié)點(diǎn)觸發(fā)指定事件,從未觸發(fā)監(jiān)聽的函數(shù)。這個(gè)方法類似于jQuery中的trigger方法,主動(dòng)觸發(fā)某個(gè)element上的監(jiān)聽方法。

溫馨提示:上面說到了可以使用腳本去觸發(fā)一個(gè)事件的發(fā)生,那如果要區(qū)分這個(gè)事件是用戶真實(shí)觸發(fā)還是腳本觸發(fā)該怎么辦呢?可以使用event對(duì)象下的 isTrusted 屬性。event.isTrusted:用戶觸發(fā)的事件返回true,腳本觸發(fā)的返回false。
2、監(jiān)聽函數(shù)
dom提供三種方式,用來為事件綁定監(jiān)聽函數(shù)。
2.1、on-屬性
就是行內(nèi)點(diǎn)擊事件,<div onclick="myClick()">點(diǎn)我</div>

2.2、element節(jié)點(diǎn)的事件屬性
window.onload=doSomething;
div.onclick=function(event){console.log('觸發(fā)事件');};
使用這個(gè)方法指定的監(jiān)聽函數(shù),只會(huì)在冒泡階段觸發(fā)。
2.3、addEventListener方法
使用 html標(biāo)簽 on-屬性,違反了html和js代碼分離原則;使用 element節(jié)點(diǎn)的事件屬性 的缺點(diǎn)是,同一個(gè)事件只能定義一個(gè)監(jiān)聽函數(shù),也就是說,如果定義兩次onclick屬性,后一次定義會(huì)覆蓋前一次。因此,這兩種方法都不推薦使用。
推薦使用 addEventListener 有點(diǎn)如下:
①、可以針對(duì)同一個(gè)事件,添加多個(gè)監(jiān)聽函數(shù)。
②、能夠指定在哪個(gè)階段(捕獲階段還是冒泡階段)觸發(fā)回監(jiān)聽函數(shù)。
③、除了DOM節(jié)點(diǎn),還可以部署在window、XMLHttpRequest等對(duì)象上面,等于統(tǒng)一了整個(gè)JavaScript的監(jiān)聽函數(shù)接口。
2.4、this對(duì)象的指向
使用addEventListener 觸發(fā)函數(shù)中的this指向 element對(duì)象。
使用on-屬性,觸發(fā)函數(shù)中的this不會(huì)指向觸發(fā)事件的元素節(jié)點(diǎn)。

3、事件傳播
3.1、事件傳播的三個(gè)階段
事件在dom之間傳播有三個(gè)階段:捕獲階段、目標(biāo)階段、冒泡階段
事件傳播的最上層對(duì)象是window,接著依次是document,html(document.documentElement)和body(document.dody)。也就是說,如果元素中有一個(gè)
元素,點(diǎn)擊該元素。事件的傳播順序,在捕獲階段依次為window、document、html、body、div,在冒泡階段依次為div、body、html、document、window。
注意,用戶點(diǎn)擊網(wǎng)頁的時(shí)候,瀏覽器總是假定click事件的目標(biāo)節(jié)點(diǎn),就是點(diǎn)擊位置的嵌套最深的那個(gè)節(jié)點(diǎn)(嵌套在節(jié)點(diǎn)的節(jié)點(diǎn))。所以,最底層那個(gè)節(jié)點(diǎn)的捕獲階段和冒泡階段,都會(huì)顯示為target階段。
如果希望事件到某個(gè)節(jié)點(diǎn)為止,不再傳播,可以使用事件對(duì)象的stopPropagation方法。

4、自定義事件和事件模擬
除了瀏覽器預(yù)定義的那些事件,用戶還可以自定義事件,然后手動(dòng)觸發(fā)。

這種方式IE不支持。
5、事件冒泡
e.preventDefault(); // 只阻止事件的默認(rèn)行為,但不能阻止事件往上冒泡。
window.event.returnValue = false; //IE中阻止函數(shù)器默認(rèn)動(dòng)作的方式?
e.stopPropagation(); // 可以阻止事件冒泡
e.cancelBubble = true; // IE下阻止事件冒泡
比較暴力的方式有:
return false; // 阻止事件冒泡
擴(kuò)展:
e.stopImmediatePropagatio() //同一節(jié)點(diǎn)添加多個(gè)點(diǎn)擊事件時(shí),使用這個(gè)API可以控制后續(xù) handle是否執(zhí)行
Keeps the rest of the handlers from being executed and prevents the event from bubbling up the DOM tree.
比如一個(gè) div 添加?addEventListener? click事件,添加兩次,當(dāng)我們點(diǎn)擊這個(gè)div時(shí),這兩個(gè)監(jiān)聽事件都會(huì)執(zhí)行,那能不能控制在第一個(gè)監(jiān)聽回調(diào)函數(shù),控制第二個(gè)回調(diào)函數(shù)不執(zhí)行呢?可以。在第一個(gè)回調(diào)函數(shù)執(zhí)行?e.stopImmediatePropagatio() ,第二個(gè)函數(shù)就不會(huì)執(zhí)行了