js的事件委托


什么是事件委托呢?

首先,委托呢,就是讓別人來做,這個事件本來是加在某些元素上的,然而你卻加到別人身上來做,完成這個事件。舉個例子,比如說送快遞,如果一個快遞員送一個公司的快遞,他可以選擇在公司聯系每個人來取這個快遞,當然另一種方法就是把快遞讓前台的MM代收,然后公司的人只要自己來前台取就ok了,雖然結果是一樣的,但是效率卻變快了許多。這里面可以把員工來取快遞的行為看作是事件冒泡(什么是事件冒泡上篇文章有提)。

特別注意:

事件委托是通過事件冒泡實現的,所以如果子級的元素阻止了事件冒泡,那么事件委托也將失效!

舉個簡單的事件委托例子:

下面代碼是一個普通的事件綁定

 

<ul id="ul">
  <li>aaaaaaaa</li>
  <li>bbbbbbbb</li>
  <li>cccccccc</li>
</ul>
window.onload = function(){
  var oUl = document.getElementById("ul");
  var aLi = oUl.getElementsByTagName("li");

  for(var i=0; i<aLi.length; i++){
    aLi[i].onmouseover = function(){
      this.style.background = "red";
    }
    aLi[i].onmouseout = function(){
      this.style.background = "";
    }
  }
}

這樣子我們可以通過for循環來遍歷每一個li節點從而實現事件的綁定。但是有一個問題,上面代碼只有三個dom界面,如果有需求需要的dom節點特別多,那么這就存在了性能的問題了。

下面我們可以用事件委托的方式來實現這樣的效果:

oUl.onmouseover = function(e){
    var e = e || window.event;
    var target = e.target || e.srcElement;
    //alert(target.innerHTML);
    if(target.nodeName.toLowerCase() == "li"){
    target.style.background = "red";
    }
  }
  oUl.onmouseout = function(e){
    var e = e || window.event;
    var target = e.target || e.srcElement;
    //alert(target.innerHTML);
    if(target.nodeName.toLowerCase() == "li"){
    target.style.background = "";
    }
  }
}

我們通過event.target來實現事件委托,這里用到了事件源:event。什么是事件源呢?記住不管在那個事件中,只要你操作的那個元素就是事件源。

顯而易見,這種方法就避免了for循環,從而提高了代碼的性能,這也是事件委托的第一個好處:提高性能!

讓我們再看一段代碼:

下面的代碼是如何操作后添加的dom元素

window.onload = function(){
  var oUl = document.getElementById("ul");
  var aLi = oUl.getElementsByTagName("li");
  var oBtn = document.getElementById("btn");
  var iNow = 4;
  for(var i=0; i<aLi.length; i++){
    aLi[i].onmouseover = function(){
      this.style.background = "red";
    }
    aLi[i].onmouseout = function(){
      this.style.background = "";
    }
  }
  oBtn.onclick = function(){
    iNow ++;
    var oLi = document.createElement("li");
    oLi.innerHTML = 1111 *iNow;
    oUl.appendChild(oLi);
  }
}

這段代碼用到了window.onload來實現事件的綁定,不過不用這個方法,那么事件肯定是失效。因為你綁定事件時根本就不存在這個dom元素,那么事件必然事件。

而事件委托就不會有這種問題。

window.onload = function(){
  var oUl = document.getElementById("ul");
  var aLi = oUl.getElementsByTagName("li");
  var oBtn = document.getElementById("btn");
  var iNow = 4;
  oUl.onmouseover = function(e){
    var e = e || window.event;
    var target = e.target || e.srcElement;
    //alert(target.innerHTML);
    if(target.nodeName.toLowerCase() == "li"){
    target.style.background = "red";
    }
  }
  oUl.onmouseout = function(e){
    var e = e || window.event;
    var target = e.target || e.srcElement;
    //alert(target.innerHTML);
    if(target.nodeName.toLowerCase() == "li"){
    target.style.background = "";
    }
  }
  oBtn.onclick = function(){
    iNow ++;
    var oLi = document.createElement("li");
    oLi.innerHTML = 1111 *iNow;
    oUl.appendChild(oLi);
  }
}
IE:window.event.srcElement
標准下:event.target
nodeName:找到元素的標簽名

其實事件委托的核心不過是通過event.target(當前事件元素).nodeName(dom元素的標簽名)取到標簽,然后用event.target.style.xxx(例子中給的是background)來操作dom
window.event.srcElement是為了兼容ie
下面是兼容瀏覽器寫出的一個target事件
    var e = e || window.event;
    var target = e.target || e.srcElement;

這個如實事件委托的最核心,最有用的地方(個人認為),就是能夠給后插入的dom節點綁定事件。一般我們用ajax調用接口返回的是一個大的json串,然后通過這個返回json動態插入數據(dom),這時候我們使用事件委托就不會出來事件綁定失效了。

jquery下的事件委托:

$(document).on('click','li',function(){
    alert('這是一個li!!!');
});

這就是一個事件委托。其實最開始的事件委托是封裝的bind(),live()和delegate(),

首先我們先說bind()

$("ul li").bind("click", function(){
  alert('這是一個li!!!');
});

問題是,如果ul中要綁定1000個里,那么查找遍歷1000個li會導致腳本運行速度很慢,而保存1000個li元素和事件處理程序也會占用大量的內存,所以這種方式我們不推薦。

下面我們來說第二種live()

$("ul li").live("click", function(){
  alert('這是一個li!!!');
});
live()事件委托可以解決上述兩個問題。具體到代碼上,只要用jQuery 1.3新增的.live()方法代替.bind()方法即可。
但是live也是有問題的。
1.$()函數會找到當前頁面中的所有li元素並創建jQuery對象,但在確認事件目標時卻不用這個li元素集合,而是使用選擇符表達式與event.target或其祖先元素進行比較,因而生成這個jQuery對象會造成不必要的開銷。

2.默認把事件綁定到$(document)元素,如果DOM嵌套結構很深,事件冒泡通過大量祖先元素會導致性能損失。
這些問題也是.live()方法飽受詬病的一個重要原因。
為了解決上面兩個方法帶來的問題,jquery在1.4.2版本引入了一個新的delegate(),代碼如下:
 
        
$("ul li").delegate("click", function(){
  alert('這是一個li!!!');
});
 
        
jquery 1.7為了解決.bind()、.live()和.delegate()並存造成的不一致性問題,將會增加一對新的事件方法:.on()
所以現在我們用jquery都是用on綁定事件(也是我最開始寫的事件委托的方式)。jquery規定on()中的第二個參數如果是dom元素,則為事件委托,否則為正常的事件綁定。
最后:希望本文所述對大家的事件委托理解有所幫助!!!
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM