首頁 > web前端 > js教程 > javascript 中的事件委託詳解

javascript 中的事件委託詳解

高洛峰
發布: 2016-12-09 10:34:16
原創
1390 人瀏覽過

這幾天看到一個面試題,大概就是,讓你給1000個li都添加一個click事件,應該怎麼添加?大多數人第一開始的感覺可能就是,每個li上邊都添加一個唄,那要是這樣的話,估計面試的時候就會GG了,這裡就是撤出了我們的事件冒泡和捕獲機制,以及事件委託機制,對於上邊這些,我們慢慢來看.

  首先說一下事件冒泡和事件捕獲機制,事件冒泡是有微軟公司提出來的,事件捕獲是有網景公司提出來的,當時兩家是爭論的不可開交,後來w3c也沒辦法,就採取了折中的方式,事件產生後先捕捉後冒泡,

  通常,在js中監聽事件的方法共有三種,分別是:

    ele.addEventListener(type,listener,[useCapture]);//IE688不支援

~

    ele.attachEvent('on'+type,listener);//IE6~10支援,IE11不支援

    ele.onClick=function(){};///////////]三個事件階段,依序是捕獲階段,目標階段,冒泡階段,而w3c指定的dom2級規定中,使用的是addEventListener來監聽事件的.所以我們就以addEventListener來講解,首先事假冒泡就像你從往水中丟一塊石子,水中的氣泡從下邊往上冒一樣,意思為觸發事件後從子元素王父元素方向觸發,而捕獲機制則正好相反,捕獲機制是從父元素往子元素方向進行事件觸發,而addEventListener函數中的第三位參數正是來決定是使用捕獲機制還是冒泡機制的,當useCapture為true是為捕獲機制,當useCapture為false時是冒泡機制,我們看一下例子:

複製程式碼

<div class="parent">
  <div class="child">
 
  </div>
</div>
<script>
  var parent = document.getElementsByClassName(&#39;parent&#39;)[0];
  var child = document.getElementsByClassName(&#39;child&#39;)[0];
 
  parent.addEventListener(&#39;click&#39;,function(){
    console.log("这里是父元素");
  },false);
  child.addEventListener(&#39;click&#39;,function(){
    console.log("这里是子元素");
  },false);
</script>
登入後複製

 

javascript 中的事件委託詳解  當我們點擊子元素是顯示上圖,當我們將false改為true後就會發現執行順序會反過來,這就是事件冒泡和捕獲的區別,他們兩個剛好相反,

javascript 中的事件委託詳解  那麼使用這種綁定機制我們的弊端在於要去給每一個對象綁定事件會是一個特別麻煩的事情,當我們要刪除一個事件或者要改變一個事件的時候會特別的繁瑣,更重要的是,我們增加了JavaScript和dom節點之間的關聯,而且一點出現循環引用,很有可能造成內存洩露,這些都是它的弊端,

   那麼解決這種弊端的一種方法就是事件代理(event delegation),這個方法可以讓你避免去給每一個節點一一的添加事件,它的做法是將這些監聽事件去綁定到這些節點的父元素上,在父元素上的這個監聽函數自動去判斷是哪一個子元素觸發的事件,從而可以對觸發事件的子元素進行操作,這裡我們給出的例子是davidwalsh所給出的一個例子:

   現在我們有一個父元素ul和幾個li子元素,

<ul id="parent-list">
  <li id="post-1">Item 1</li>
  <li id="post-2">Item 2</li>
  <li id="post-3">Item 3</li>
  <li id="post-4">Item 4</li>
  <li id="post-5">Item 5</li>
  <li id="post-6">Item 6</li>
</ul>
登入後複製
  現在我們要實現的是,當我們點擊每一個li節點的時候,都會輸出li節點中的內容,按照上邊的寫法,你可以選中這些li,讓後給他們加上這些方法,然後等到不需要了再將他們移除,如果有100個li,1000個li呢,這將會成為你的噩夢,較好的解決方法就是給父元素添加一個監聽事件,之後的問題便是怎麼去判斷出來時哪一個li被點擊了? 我們可以在監聽事件中去判斷當前event的target來判斷是否是我們要找的節點,這裡我們有一個簡單的例子:
// 找到父元素,绑定一个监听事件
document.getElementById("parent-list").addEventListener("click", function(e) {
  // e.target是点击的元素
  // 如果它是li元素
  if(e.target && e.target.nodeName == "LI") {
    //
    console.log("List item ", e.target.id.replace("post-", ""), " was clicked!");
  }
});
登入後複製

  當ul中發生點擊事件後,因為addEventListener預設是冒泡事件,所以監聽事件會在底層事件冒泡過來時執行,在觸發了事件後,去檢測是否是我們要尋找的目標元素,如果不是,就會忽略過去,那我們不僅僅可以透過目標元素的標籤是不是我們需要的目標元素,我們還可以根據目標元素的屬性或者類名來進行檢測,利用ele.maeches這個API來進行處理,

document.getElementById("myDiv").addEventListener("click",function(e) {
  // e.target 就是当前被点击的元素
 if (e.target && e.target.matches("a.classA")) {
  console.log("Anchor element clicked!");
  }
});
登入後複製

  因此我們可以看得出來,使用事件代理這種方式,能夠給我們帶來很多的便捷,可以避免很多坑,使用事件代理是一種很強大的方法.

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板