事件是javascript跳動的心臟,是DOM所有成分結合的萬金油。當我們在WEB 上進行某些互動時,事件也就發生了。點擊某些內容,滑鼠經過特定元素,按下某些按鍵,改變視窗。當然還可能是瀏覽器上某個頁面載入完畢。通過 javascript你可以監聽特定事件的發生,為事件綁定處理函數。 DOM事件流 在DOM中,當某一個特定的HTNL元素產生事件時,該事件會在該元素節點與根節點之間按特定的順序傳播,所經過的節點都會監聽到該事件(但不一定執行該 事件對應的動作,因為未綁定事件處理函數),這個傳播過程就是DOM事件流。事件流有兩種事件順序:事件捕獲和事件冒泡。 冒泡型事件(event bubble):冒泡型事件最早由IE實現,事件就像水中的氣泡,有目標元素逐級向上冒,直到頂端的根節點 捕獲型事件(event capture):捕獲型事件有netscape實現,它與冒泡剛好相反,事件從根節點逐級派送到目標元素。 DOM標準事件模型:W3C這個紅娘將二者融合在一起就形成了DOM標準事件模型。先執行捕獲,然後再冒泡(所以,若果一個處理函數既被綁定了捕獲型事件,又被綁定了冒泡型事件,那麼這個事件處理函數會執行兩次,而且先執行捕獲型事件)。 event-buddledomevent 事件監聽器和事件處理函數 事件處理函數(有的地方叫做事件控制代碼,此稱謂容易和事件監聽器混淆,個人不推薦),用於響應某個事件而調用的函數。每一個事件都應該對應一個事件處理函數 (理論上),否則就是做無用功,浪費資源。事件發生時,瀏覽器執行對應的事件處理函數,從而實現頁面內容和使用者操作的互動。我們認為響應點擊事件的處理函 數為onclick。事件處理函數的兩種分配方式:javascript和html(內聯的事件處理函數方式早已經過去,不再討論)中。如果在 javascript中分配事件處理函數,首先需要獲得處理對象的引用,然後將函數綁定到對象的事件處理函數屬性上: 1 var link=document.getElementById("mylink");2 link.onclick=function(){3 alert("I was clicked !");4 }; 這種分配事件處理函數的特定是簡單,但不能為同一事件綁定多個事件處理函數。鑒於此缺點,現在大多數瀏覽器內建了事件監聽器來更全面的綁定事件處理函數。 在IE下的事件監聽器是attachEvent(),W3C標準型的事件監聽器是addeventListener()。 A:attachEvent() 在IE下,每個元素和window對象都有兩個方法attachEvent和detachEvent方法。 element.attachEvent("onevent",eventListener);第一個參數是事件類型名,第二個參數是事件處理函 數。在IE下處理函數調用時this指向的不再是先前註冊事件的元素,而是window(window.event的使用)。還有一點就是事件前面要 加"on"。 element.attachEvent("onevent",eventListener)刪除事件監聽器,參數一致。 B:addEventListener() 在支援W3C標準事件監聽器的瀏覽器,每個對象都可以使用addEventListener方法。該方法及支援冒泡型事件處理,也支援捕獲型事件處理。 elem.addEventListener(type,eventListener,capture),預設情況下capture取false,即為冒 泡型事件處理。addEventListener方法接受三個參數。第一個是事件類型,不需要加"on",第二個是事件處理函數,第三個是決定事件處理函 數在冒泡還是捕獲階段調用。移除事件已經註冊的監聽器用removeEventListener。 和註冊的時候參數一致element.removeEventListener('event', eventListener, useCapture); 跨瀏覽器的事件監聽器 既然IE和W3C註冊時間監聽器的方案是不同的,對於支援addEventListener方法的瀏覽器,只要需要事件監聽器指令碼就都需要調用addEventListener方法;而對於不支援該方法的IE瀏覽器,使用事件監聽器時則需要調用attachEvent方法。那麼我們要相容瀏覽器也不是什麼困難的事,下面是具體的相容瀏覽器的註冊事件監聽器方案: 複製代碼 1 var eventUtil={ 2 //註冊 3 addHandler:function(elem,type,handler){ 4 if(elem.addEventListener){ 5 elem.addEventListener(type,handler,false); 6 }else if(elem.attachEvent){ 7 elem.attachEvent("on"+type,handler); 8 }else{ 9 elem["on"+type]=handler;10 }11 }12 //移除13 removehandler:function(elem,type,handler){14 if(elem.removeListener){15 elem.removeListener(type,handler,false)16 }else if(elem.detachEvent){17 elem.detachEvent("on"+type,handler)18 }else{19 elem["on"+type]=null;20 }21 }22 }複製代碼 當事件發生的時候觸發事件處理函數,W3C情況下,event對象將自動在事件處理函數內可用,這個對象包含了該事件的全部資訊。但在IE下是通過全域對象window下的event屬性來包含這些資訊的。跨瀏覽器在擷取事件對象和事件目標: 複製代碼 1 var eventUtil={ 2 handler:function(event){ 3 event=event||window.event 4 do somesthing 5 } 6 getTarget;function(event){ 7 return event,target||event.srcElement 8 9 }10 }複製代碼阻止事件預設行為和阻止事件冒泡 阻止事件冒泡,停止冒泡型事件的進一步傳遞(取消事件傳遞不只是停止IE和DOM標準共有的冒泡型事件,我們還可以停止支援DOM標準瀏覽器的捕捉型事件,用stopPropagation()方法。 阻止事件的預設行為,通常瀏覽器在事件處理完後會執行與該事件關聯的預設操作。例如,如果表單中input type 屬性是 “submit”,點擊後在事件傳播完瀏覽器就自動認可表單。又例如,input 元素的 keydown 事件發生並處理後,瀏覽器預設會將使用者鍵入的字元自動追加到 input 元素的值中。 A:停止事件冒泡的處理方法(把此函數放在目標元素處理函數的最後一行): 複製代碼1 function stopHandle(event){2 event=event||window.event3 if(event.stopPropagation){4 event.stopPropagation();5 }else{6 event.cancelBubble=true;7 } 9 }複製代碼B:阻止事件的預設行為 複製代碼1 function defaultHandle(event){2 event=event||window.event3 if(event.preventDefault){4 event.preventDefault();5 }else{6 event.returnValue=false;7 } 9 }複製代碼 事件委託 事件委託是建立在事件冒泡的基礎上的,有這麼一個例子,如果你有一個多行的表格,在每個<tr>上綁定點擊事件是個非常影響效能的大問題。大 多數庫或者架構的做法是使用事件委託。事件委託將事件綁定在包含目標元素的容器元素上,然後通過判斷點擊的目標子項目來觸發相應的事件。 複製代碼1 var myTable=dcument.getElementById("tab");2 myTable.addEventListener(click,function(event){3 event=event||window.event;4 var targetNode=event.target||event.srcElement5 if(targetNode.nodeName.toLowerCase()=="tr"){6 alert("you have clicked");7 }8 })