什么是事件?
事件是文檔和瀏覽器窗口中發生的特定的交互瞬間。 事件是javascript應用跳動的心臟,也是把所有東西黏在一起的膠水,當我們與瀏覽器中web頁面進行某些類型的交互時,事件就發生了。
事件可能是用戶在某些內容上的點擊,鼠標經過某個特定元素或按下鍵盤上的某些按鍵,事件還可能是web瀏覽器中發生的事情,比如說某個web頁面加載完成,或者是用戶滾動窗口或改變窗口大小。
什么是事件流:
事件流描述的是從頁面中接受事件的順序,但有意思的是,微軟(IE)和網景(Netscape)開發團隊居然提出了兩個截然相反的事件流概念,IE的事件流是事件冒泡流(event bubbling),而Netscape的事件流是事件捕獲流(event capturing)。
下面說一下事件冒泡和事件捕獲的概念:
事件冒泡和事件捕獲是描述事件觸發事件時序問題的術語,事件捕獲指的是從document到觸發事件的那個節點,也就是說自上而下的去觸發事件,相反的,事件冒泡是自下而上的去觸發事件,綁定事件方法的第三個參數,就是控制事件觸發順序是否為事件捕獲,true為事件捕獲,false為事件冒泡,jQuery的e.stopPropagation會阻止冒泡,意思就是到我為止,我的爹和祖宗的事件就不要觸發了。
第一種:事件冒泡
IE提出的事件流叫做事件冒泡,即事件開始時由最具體的元素接收,然后逐級向上傳播到較為不具體的節點,看一下以下示例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6 </head>
7 <body onclick="bodyClick()">
8
9 <div onclick="divClick()">
10 <button onclick="btn()">
11 <p onclick="p()">點擊冒泡</p>
12 </button>
13 </div>
14 <script>
15
16 function p(){ 17 console.log('p標簽被點擊') 18 } 19 function btn(){ 20 console.log("button被點擊") 21 } 22 function divClick(event){ 23 console.log('div被點擊'); 24 } 25 function bodyClick(){ 26 console.log('body被點擊') 27 } 28
29 </script>
30
31 </body>
32 </html>
執行順序: p=>button=>div=>body
正如上面我們所說的,它會從一個最具體的的元素接收,然后逐級向上傳播, p=>button=>div=>body..........事件冒泡可以形象地比喻為把一顆石頭投入水中,泡泡會一直從水底冒出水面,也就是說從小到大開始傳播。
第二種:事件捕獲
網景公司提出的事件流叫事件捕獲流。
事件捕獲流的思想是不太具體的DOM節點應該更早接收到事件,而最具體的節點應該最后接收到事件,針對上面同樣的例子,點擊按鈕,那么此時click事件會按照這樣傳播:(下面我們就借用addEventListener的第三個參數來模擬事件捕獲流),也就是上面的例子就會倒過來。
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6 </head>
7 <body>
8
9 <div>
10 <button>
11 <p>點擊捕獲</p>
12 </button>
13 </div>
14 <script>
15 var oP=document.querySelector('p'); 16 var oB=document.querySelector('button'); 17 var oD=document.querySelector('div'); 18 var oBody=document.querySelector('body'); 19
20 oP.addEventListener('click',function(){ 21 console.log('p標簽被點擊') 22 },true); 23
24 oB.addEventListener('click',function(){ 25 console.log("button被點擊") 26 },true); 27
28 oD.addEventListener('click', function(){ 29 console.log('div被點擊') 30 },true); 31
32 oBody.addEventListener('click',function(){ 33 console.log('body被點擊') 34 },true); 35
36 </script>
37
38
39
40 </body>
41 </html>
正如我們看到的,和冒泡流萬全相反,從最不具體的元素接收到最具體的元素接收事件 body=>div=>button=>p
DOM事件流:
‘DOM2級事件’規定的事件流包含3個階段,事件捕獲階段、處於目標階段、事件冒泡階段。首先發生的事件捕獲為截獲事件提供機會,然后是實際的目標接收事件,最后一個階段是事件冒泡階段,可以在這個階段對事件做出響應。
在DOM事件流中,事件的目標在捕獲階段不會接收到事件,這意味着在捕獲階段事件從document到<p>就停止了,下個階段是處於目標階段,於是事件在<p>上發生,並在事件處理中被看成冒泡階段的一部分,然后,冒泡階段發生,事件又傳播回document。

流程就是先捕獲,然后處理,最后再冒泡出去
關於DOM 2級事件處理程序:
DOM 2級事件定義了兩方法:用於處理添加事件和刪除事件的操作: 添加事件 addEventListener() 刪除事件 removeEventListener(),所有DOM節點中都包含這兩個方法,並且他們都包含3個參數:
(1) 要處理的事件方式(例如:click,mouseover,dbclick.....)
(2)事件處理的函數,可以為匿名函數,也可以為命名函數(但如果需要刪除事件,必須是命名函數)
(3)一個布爾值,代表是處於事件冒泡階段處理還是事件捕獲階段(true:表示在捕獲階段調用事件處理程序;false:表示在冒泡階段調用事件處理程序)
使用DOM 2級事件處理程序的主要好處是可以添加多個事件處理程序,事件處理會按照他們的順序觸發,通過addEventListener添加的事件只能用removeEventListener來移除,移除時傳入的參數與添加時使用的參數必須相同,這也意味着添加的匿名函數將無法移除,(注意:我們默認的第三個參數都是默認false,是指在冒泡階段添加,大多數情況下,都是將事件處理程序添加到事件的冒泡階段,這樣可以最大限度的兼容各個瀏覽器)
