事件綁定/委託

 

首先要作的第一件事情就是要先搞清楚什麼是事件委託/綁定,這個東西有什麼用,有什麼優勢和缺點,這樣才能更好的去了解學習相關的知識。html

那就先作第一件事,認識事件綁定,不過說這個以前得先了解一下DOM事件流。node

一、什麼是事件流函數

事件流描述的是從頁面中接收事件的順序。但有意思的是,IE 和 Netscape 開發團隊竟然提出了差
很少是徹底相反的事件流的概念。IE 的事件流是事件冒泡流,而 Netscape Communicator 的事件流是事
件捕獲流。學習

a、IE中的事件流測試

IE 的事件流叫作事件冒泡(event bubbling),即事件開始時由最具體的元素(文檔中嵌套層次最深
的那個節點)接收,而後逐級向上傳播到較爲不具體的節點(也能夠說是由子到父或者說從下到上)。this

若是你單擊了頁面中的 <div> 元素,那麼這個 click 事件會按照以下順序傳播:
(1) <div>
(2) <body>
(3) <html>
(4) documentspa

代碼以下:設計

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Event Bubbling Example</title>
5 </head>
6 <body>
7 <div id="myDiv">Click Me</div>
8 </body>
9 </html>

b、Netscape提出的事件流3d

Netscape Communicator團隊提出的另外一種事件流叫作事件捕獲(event capturing)。事件捕獲的思想
是不太具體的節點應該更早接收到事件,而最具體的節點應該最後接收到事件。事件捕獲的用意在於在
事件到達預約目標以前捕獲它。code

若是仍之前面的 HTML 頁面做爲演示事件捕獲的例子,那麼單擊 <div>元素就會如下列順序觸發 click 事件。

(1)  document

(2) <html>
(3) <body>
(4) <div>

「DOM2級事件」規定的事件流包括三個階段:事件捕獲階段、處於目標階段和事件冒泡階段。首
先發生的是事件捕獲,爲截獲事件提供了機會。而後是實際的目標接收到事件。最後一個階段是冒泡階
段,能夠在這個階段對事件作出響應。

再貼一個很形象的圖片:

 二、事件處理程序

a、HTML事件處理程序

某個元素支持的每種事件,均可以使用一個與相應事件處理程序同名的 HTML 特性來指定。

b、 DOM0 級事件處理程序

經過 JavaScript 指定事件處理程序的傳統方式,就是將一個函數賦值給一個事件處理程序屬性

c、DOM2 級事件處理程序

DOM2級事件定義了兩個方法,用於處理指定和刪除事件處理程序的操做: addEventListener()和 removeEventListener()

 

三、什麼是事件委託/綁定

對「事件處理程序過多」問題的解決方案就是事件委託。事件委託利用了事件冒泡,只指定一個事
件處理程序,就能夠管理某一類型的全部事件。例如, click 事件會一直冒泡到 document 層次。也就
是說,咱們能夠爲整個頁面指定一個 onclick 事件處理程序,而沒必要給每一個可單擊的元素分別添加事
件處理程序。

那事件委託有什麼用呢?

//1.事件未綁定第一個問題 事件覆蓋問題
//沒有加事件綁定時出現的問題

 <div style="height:100px; width:100px; background="red"; ">測試</div>
1
var box = document.getElementsByTagName('div')[0]; 2 box.onclick = function() { 3 alert(1); 4 }; 5 box.onclick = function() { 6 alert(2); 7 }; 8 box.onclick = function() { 9 alert(3); // 只有這一個會顯示 前兩個都會被覆蓋掉 10 };

//有加事件綁定時

1 box.addEventListener("click", function() {
2         alert(1) //這裏的每個都會顯示出來
3     }, false)
4     box.addEventListener("click", function() {
5         alert(2) //這裏的每個都會顯示出來
6     }, false)
7     box.addEventListener("click", function() {
8         alert(3) //這裏的每個都會顯示出來
9     }, false)

//2.事件綁定第二個問題    相同函數屏蔽問題

1 box.addEventListener("click",fn, false)
2     box.addEventListener("click",fn, false)
3     function fn(){
4         alert(1)
5     }

//3.事件綁定第三個問題 傳遞this問題
//沒有事件綁定時的this

 1 box.onclick = function() {
 2         fn();
 3     };
 4 
 5     function fn() {
 6         alert(this); //window  這裏的this指的仍是window
 7     };
 8 
 9     //有事件綁定時的this
10     box.addEventListener('click', fn, false);
11 
12     function fn() {
13         alert(this); //div   this的值從上面傳過來了
14     };

//4.事件綁定第三個問題      添加一個事件會被覆蓋或者只執行一次

 1 box.onclick = function() {
 2         alert(100);
 3     };
 4     box.onclick = fn;
 5 
 6     function fn() {
 7         alert(200);
 8     };
 9 
10     box.addEventListener("click", function() {
11         alert(100);
12     }, false)
13     box.addEventListener("click", fn, false)
14 
15     function fn() {
16         alert(200);
17     };

//IE中 event對象的獲取

1 box.onclick=function(ev){
2         alert(ev)  //傳統方法IE沒法經過參數獲取ev
3     }
4     box.addEventListener("click",function(ev){
5         alert(ev)   //能夠經過事件綁定來獲取
6     })

最後就是兼容封裝

 1 //兼容寫法封裝
 2     //添加事件綁定
 3     function addEvent(obj, event, fn, bool) { //obj對象  event:事件  fn綁定函數  bool:是否捕獲
 4         if (obj.addEventListener) {
 5             obj.addEventListener(event, fn, bool);
 6         } else {
 7             obj.attachEvent('on' + event, fn)
 8         }
 9     }
10 
11     //刪除事件綁定
12     function removeEvent(obj, event, fn, bool) { //obj對象  event:事件  fn綁定函數
13         if (obj.removeEventListener) {
14             obj.removeEventListener(event, fn, bool);
15         } else {
16             obj.detachEvent('on' + event, fn)
17         }
18     }

 

window.onload = function(){
  var oUl = document.getElementById("ul1");
  oUl.onclick = function(ev){
    var ev = ev || window.event;  //event兼容寫法
    var target = ev.target || ev.srcElement;  //target兼容寫法
    if(target.nodeName.toLowerCase() == 'li'){
         alert(target.innerHTML);
    }
  }
}

 

 

更加詳細的去參考高級程序設計第13章

 

事件流

事件流

相關文章
相關標籤/搜索