淺談JavaScript的事件(事件處理程序)

  事件就是用戶或者瀏覽器自身執行的某種動做。諸如click、load和mouseover,都是事件的名字。而響應某個事件的函數就叫事件處理程序。事件處理程序的名字以「on」開頭,好比click事件的事件處理程序是onclick。爲事件指定事件處理程序的方式有多種方式。瀏覽器

  • HTML事件處理程序

  元素支持的事件,均可以使用與相應事件處理程序同名的HTML特性來指定。這個特性的值能支持必定的JavaScript代碼。例如,在單擊按鈕的時候執行一些JavaScript代碼。 <div id="aa" onclick="console.log('div')" style="width: 100px;">2222</div> ,當單擊這個div的時候,會在瀏覽器的控制檯中輸出div。這個特性是經過JavaScript來實現的,不能在其中使用未經轉義的HTML語法字符,例如和號(&)、雙引號("")、單引號('')、小於號(<)或者大於號(>)。函數

  在HTML中定義的事件處理程序能夠包含要執行的具體動做,也能夠調用定義在其餘頁面的腳本。this

1  function divClick(e){ 2              var target=e.target; 3              console.log("div"); 4              //stopBubble(e);
5          }

 <div id="aa" onclick="divClick(event);" style="width: 100px;">2222</div> spa

  上面的代碼中,點擊div以後就會調用divClick函數。這個函數是單獨定義的script腳本中的,固然也能夠定義在一個外部文件中。事件處理程序中的代碼,能夠訪問全局的方法。上面的代碼中,一樣能夠傳遞event參數以及this參數。event參數可以獲取事件的類型參數等,經過this可以獲取點擊對象自己。code

1  function divClick(e){ 2              //var target=e.target;
3              console.log($(e).text());//222
4              //stopBubble(e);
5          }

 <div id="aa" onclick="divClick(this);" style="width: 100px;">2222</div> 對象

  在HTML中指定事件處理程序有必定的缺點:存在必定的時差,用戶可能在頁面一出現就觸發相應的事件,可是事件處理程序尚不具有執行的條件。上面的例子上,若是divClick函數定義在div的下方,咱們在函數還沒有解析以前,就點擊div,這樣就會致使報錯。blog

  另外一個缺點是,這樣的事件處理程序的做用域鏈在不一樣的瀏覽器中會致使不一樣結果。不一樣JavaScript引擎遵循的標識符解析規則略有差別,極可能在訪問非限定對象時出錯。seo

  經過HTML指定事件處理程序的最後一個缺點是HTML與JavaScript代碼的緊密耦合。若是要更換事件處理程序就須要改動兩個地方:JavaScript和HTML。事件

  • DOM級事件處理程序

  經過JavaScript指定事件處理程序的傳統方式是將一個函數賦值給事件處理程序屬性。經過JavaScript指定事件處理程序有兩個優點:簡單和瀏覽器兼容性好。要使用JavaScript指定事件處理程序,首先必須獲取一個元素的對象引用。每一個元素都有本身的事件處理程序,這個屬性一般是所有小寫,好比onclick。ip

  

1 <div id="aa"  style="width: 100px;">2222</div>
2         <script>
3             var a=document.getElementById("aa"); 4             a.onclick=function(e){ 5                 var target=e.target; 6                 var text=target.innerHTML; 7                 console.log(text);//222
8  } 9         </script>

  上面的代碼,經過文檔對象獲取了對象的引用,而後爲它指定了onclick事件處理程序。e爲點擊事件的參數,經過該參數可以獲取點擊事件的對象,即target。經過對象能夠進一步獲取對象的屬性。

  

1 <div id="aa"  style="width: 100px;">2222</div>
2         <script>
3             $("#aa").click(function(e){ 4                 var target=e.target; 5                 var text=target.innerHTML; 6                 console.log(text);//222
7  }); 8         </script>

  這段代碼與上面的例子實現的是同樣的效果,可是這個是經過JQuery來實現的。

  DOM2級事件處理程序定義了兩個方法,用於處理指定和刪除事件處理程序的操做:addEventListener和removeEventListener。全部DOM節點都包含這兩個方法,而且他們接收3個參數:要處理的事件名、做爲事件處理程序的函數和一個布爾值。布爾值若是爲true,表示在捕獲階段執行事件處理程序,若是爲false,表示在冒泡階段調用事件處理程序。

1 <div id="aa"  style="width: 100px;">2222</div>
2         <script>
3             var a=document.getElementById("aa"); 4             a.addEventListener("click",function(e){ 5                 console.log(this.id); 6             },false); 7         </script>

  上面的例子經過addEventListener爲元素aa添加了一個click事件。經過事件處理程序可以訪問到元素,this和元素處在同一個做用域鏈。

  經過DOM2級能夠經過添加多個事件處理程序。事件處理程序會按照添加的順序依次觸發。

1 var a=document.getElementById("aa"); 2             a.addEventListener("click",function(e){ 3                 console.log(this.id); 4             },false); 5             a.addEventListener("click",function(e){ 6                 console.log(this.innerHTML); 7             },false);

  經過addEventListener添加的事件處理程序,能夠經過removeEventListener來移除事件處理程序。可是,有時候咱們會走入一個誤區。

1 var a=document.getElementById("aa"); 2             a.addEventListener("click",function(e){ 3                 console.log(this.id); 4             },false); 5             a.removeEventListener("click",function(e){ 6                 console.log(this.id); 7             },false);

  上面的代碼咱們使用removeEventListener方法移除事件處理程序,可是並無起做用。在使用addEventListener和removeEventListener的時候,第二個事件處理程序函數必須是同一個函數纔會有做用,咱們對上面的代碼做一個修改,就能夠了。

1 var a=document.getElementById("aa"); 2             var callback=function(e){ 3                 console.log(this.id); 4  } 5             a.addEventListener("click",callback,false); 6             a.removeEventListener("click",callback,false);

  上面的代碼中,咱們在addEventListener和removeEventListener中調用的是同一個方法,因此元素aa已經沒有點擊事件。

  對於IE8以及IE8如下瀏覽器來講,它們並無上述的兩個方法,可是提供了attachEvent和detachEvent兩個方法。這兩個只須要傳遞兩個參數:第一參數事件程序名稱,第二個事件處理程序函數。

1 var a=document.getElementById("aa"); 2             var callback=function(e){ 3  console.log(e.target.innerHTML); 4  } 5             //a.addEventListener("click",callback,false);
6             //a.removeEventListener("click",callback,false);
7             a.attachEvent("onclick",callback);

  上面的代碼經過attachEvent添加了事件處理程序,可是attachEvent與addEventListener不同。在attachEvent的事件處理程序函數中this是指向window的,咱們沒法獲取元素對象。

  

1 var a=document.getElementById("aa"); 2             var callback=function(e){ 3                 console.log(this.id); 4  } 5             //a.addEventListener("click",callback,false);
6             //a.removeEventListener("click",callback,false);
7             a.attachEvent("onclick",function(e){ 8  callback.call(a,e); 9             });

  上面的代碼,咱們經過call修改了this的指向,可是這樣會帶來另一個問題,怎麼detachEvent?

  • 跨瀏覽器事件處理程序  

  爲了以跨瀏覽器的事件處理程序,開發人員能夠封裝適合本身的js庫。

 1 var EventUtil={  2                 addEvent:function(element,type,fn){  3                     if(element.addEventListener){  4                         element.addEventListener(type,fn,false);  5  }  6                     else if(element.attachEvent){  7                         element.attachEvent("on"+type,fn);  8  }  9                     else{ 10                         element["on"+type]=fn; 11  } 12  }, 13                 removeEvent:function(element,type,fn){ 14                     if(element.removeEventListener){ 15                         element.removeEventListener(type,fn,false); 16  } 17                     else if(element.detachEvent){ 18                         element.detachEvent("on"+type,fn); 19  } 20                     else{ 21                         element["on"+type]=null; 22  } 23  } 24  }; 25             var aa=document.getElementById("aa"); 26             var func=function(e){ 27  console.log(e.type); 28                 EventUtil.removeEvent(aa,"click",func); 29  } 30             EventUtil.addEvent(aa,"click",func);

  上面的EventUtil封裝了一個跨瀏覽器的對象,包含兩個方法addEvent和removeEvent。在第25行獲取元素對象引用,26行定義了fn函數,30行調用addEvent添加了事件處理程序。這個事件處理程序只能執行一次,由於咱們在func函數中又調用了removeEvent函數。

相關文章
相關標籤/搜索