js中的事件委托


事件委托,顧名思義,就是將本來需要 A 處理的事情,委托給 B 來處理。在 JavaScript 中的事件委托又稱事件代理,事件委托就是利用事件冒泡,只指定一個事件處理程序,就可以管理某一類型的所有事件。當然,如果子元素阻止了事件冒泡,那么委托也就沒法實現了。

如何舉個例子形容呢:
有三個同事預計會在周一收到快遞。為簽收快遞,有兩種辦法:一是三個人在公司門口等快遞;二是委托給前台 MM 代為簽收。現實當中,我們大都采用委托的方案(公司也不會容忍那么多員工站在門口就為了等快遞)。前台 MM 收到快遞后,她會判斷收件人是誰,然后按照收件人的要求簽收,甚至代為付款。這種方案還有一個優勢,那就是即使公司里來了新員工(不管多少),前台 MM 也會在收到寄給新員工的快遞后核實並代為簽收。

這里其實還有 2 層意思的:

第一,現在委托前台的同事是可以代為簽收的,即程序中的現有的 dom 節點是有事件的;

第二,新員工也是可以被前台 MM 代為簽收的,即程序中新添加的 dom 節點也是有事件的。

下面我們舉一個代碼例子:

我們要實現一個需求,當鼠標懸浮在 li 元素上,li 元素背景變成紅色,離開時,去掉背景。代碼如下:

<ul id="ul">
  <li>a</li>
  <li>b</li>
  <li>c</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 = '';
    };
  }
};

我們循環遍歷每一個 li 元素,並為之加上 mouserover 和 mouseout 事件。這只適用於 li 元素特別少的情況,如果 li 元素特別多,定會引起性能問題。還有一個問題,如果這時候動態添加了一個 li 元素,這個元素是沒法響應事件的,因為沒有給他綁定任何事件。

通過事件委托實現

window.onload=function(){
    var oUl = document.getElementById('ul');
    oUl.onmouseover = function(e){
        var e = e || window.event;
        var target = e.target || e.srcElement;
        if(target.nodeName.toLowerCase() == "li"){
        target.style.background = "red";
        }
    }
    oUl.onmouseout = function(e){
        var e = e || window.event;
        var target = e.target || e.srcElement;
        if(target.nodeName.toLowerCase() == "li"){
        target.style.background = "";
        }
    }
}
}

在這段代碼中,通過 event.target 來實現事件委托。這種方法避免了循環,提高了性能。

標准瀏覽器用 event.target,IE 瀏覽器用 event.srcElement

新問題,如果 li 還包含了其他元素怎么辦呢,這樣 target 就不是 li 了。
解決辦法:

var oUl = document.getElementById('test');
oUl.addEventListener('click', function(ev) {
  var target = ev.target;
  while (target !== oUl) {
    if (target.tagName.toLowerCase() == 'li') {
      console.log('li click~');
      break;
    }
    target = target.parentNode;
  }
});

另外一個例子:

<div id="box">
  <input type="button" id="add" value="添加" />
  <input type="button" id="remove" value="刪除" />
  <input type="button" id="move" value="移動" />
  <input type="button" id="select" value="選擇" />
</div>

不用事件委托:

window.onload = function() {
  var Add = document.getElementById('add');
  var Remove = document.getElementById('remove');
  var Move = document.getElementById('move');
  var Select = document.getElementById('select');

  Add.onclick = function() {
    alert('添加');
  };
  Remove.onclick = function() {
    alert('刪除');
  };
  Move.onclick = function() {
    alert('移動');
  };
  Select.onclick = function() {
    alert('選擇');
  };
};

使用事件委托:

window.onload = function() {
  var oBox = document.getElementById('box');
  oBox.onclick = function(ev) {
    var ev = ev || window.event;
    var target = ev.target || ev.srcElement;
    if (target.nodeName.toLocaleLowerCase() == 'input') {
      switch (target.id) {
        case 'add':
          alert('添加');
          break;
        case 'remove':
          alert('刪除');
          break;
        case 'move':
          alert('移動');
          break;
        case 'select':
          alert('選擇');
          break;
      }
    }
  };
};


免責聲明!

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



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