js事件委託詳解

​       今天呢,咱們來說說事件委託,有的相關資料叫事件代理.

​      首先呢,先來講講事件委託的起源:由於事件處理程序可以爲web應用提供交互能力,因此很多開發人員會不分青紅皁白的向頁面中添加大量的處理程序.在js中,添加到頁面的事件處理程序數量直接關係到頁面的整體運維性能.導致這一問題的原因是多方面的.首先:

     1 函數都是對象,都會佔用內存,內存中對象越多,性能越差

     2 事先指定所有的事件處理程序而導致dom訪問次數,會延遲整個頁面的交互的就緒事件.

所以:對事件處理程序過多問題的解決方案就是事件委託.

舉個栗子
在這裏插入圖片描述

 <ul id = 'ul1'>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
	...
    <li>100</li>
 </ul>

​       如果咱們頁面上有100個li標籤,如果要實現點擊li變成紅色,我們雖然可以用for循環,給每個li添加事件,那這樣就爲它們添加了100個事件處理程序,若在一個複雜的web程序中,都使用這種方式,那結果就是數不清的添加事件處理.那麼這裏是極其浪費資源的.所以這裏可以得到一個結論:

​       事件委託,最重要的功能就是提高程序運行效率.

​      既然出來了事件委託,那咱們講講事件委託的原理.先來個概念:事件流.

​ 事件流分爲
1.事件捕獲
​       當一個事件觸發後,從Window對象觸發,不斷經過下級節點,直到目標節點。在事件到達目標節點之前的過程就是捕獲階段。所有經過的節點,都會觸發對應的事件
2.事件冒泡
​       當事件到達目標節點後,會沿着捕獲階段的路線原路返回。同樣,所有經過的節點,都會觸發對應的事件
在這裏插入圖片描述
那現在直接上代碼,帶大家來了解什麼是事件捕獲和事件冒泡

  <div id = 'div1'>
       爺爺
        <div id = 'div2'>
           父親
          <div id = 'div3'>
            孫子
          </div>
        </div>
   </div>
 <style>
     div{padding: 50px; color: white; font-size: 20px;}
     #div1{background-color: orange;}
     #div2{background-color: blue;}
     #div3{background-color: red;}
 <style>

     例如,咱們都給這三個div同時綁定了點擊事件,那我在點擊孫子時,按常理來說,是不是也是點擊了父親和爺爺呢,所以呢,咱們點擊了孫子的click事件,那麼這個事件就會向dom樹上傳播,也就是這個順序

  div3>div2>div1>body>html>document.....

   那麼呢,這就是事件冒泡,而事件捕獲正好相反,在事件捕獲過程中,document首先接到click事件,然後沿着document向下,一直傳播到事件的實際目標.也就是按着這個順序

   document>html>body>div1>div2>div3

    但傳統的事件的綁定沒有辦法實現事件捕獲的,咱們的默認事件流還是事件冒泡!
    事件冒泡:由裏向外逐級向外觸發(必須由父子關係的組件)(默認事件流)
    事件捕獲:由外向裏逐級向外觸發(必須由父子關係的組件) 傳統的事件的綁定沒有辦法實現
    好,這裏有人問了,既然咱們講的是事件委託,爲什麼這裏要將事件流的事件冒泡和事件捕獲呢.其實咱們要實現的事件委託原理就是事件冒泡!那接着來說咱們上述的案例,現在需求來了,如果要給100個,1000個li標籤同時綁定onclick事件,咱們這裏用最高效的方式進行綁定,沒錯,就是事件委託.

   <ul id = 'ul1'>
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
  	...
      <li>100</li>
  </ul>

     要給這100個li標籤綁定事件,當我們單擊li時,當前被點擊的li標籤背景顯示紅色.同時呢,這裏又產生了一個問題:父級那麼多子元素,怎麼區分事件本應該是哪個子元素的?答案是咱們的事件中有個event對象,而event對象裏記錄的有“事件源”,它就是發生事件的子元素。咱們在寫的時候,這個獲取event的事件源是有IE兼容性的. 在低版本中的獲取是window.event.srcElement;而在咱們其他瀏覽器是可以直接通過event.target獲取的,咱們一般的寫法是

  var target = event.target || window.event.srcElement;//短路操作

那咱們通過事件委託來實現

      var oUl = document.getElementById("ul1");
      //委託ul上的點擊事件,將當前點擊的li節點變成紅色。
      oUl.onclick = function(ev){
           //獲取事件對象短路操作,兼容IE
           var e = ev || window.event;
           //獲取事件源 target  這裏也要兼容IE
           var target = e.target || window.event.srcElement;
           //判斷target是否符合要求的元素節點
           if(target.tagName.toLowerCase() == "li"){
			 //將當前點擊這個li節點變成紅色
             target.style.backgroundColor = 'red';
            }
      }

這裏咱們就真真實實的實現了一個事件委託,而且,就只綁定了一個事件,把這個事件給了ul標籤.咱們通過點擊li,然後通過冒泡原理 子元素身上的事件會冒泡到父元素身上 那這裏是不是比傳統的實現方式方便了很多呢,而且節省了大量的內存資源.沒有那麼多事件處理程序了,這是對web程序的一個性能的優化.綜上,可以總結出要實現事件委託,必須遵從的三個條件:
     1、找要添加行爲的節點的父節點或者祖先節點
     2、將事件綁定在找到的父節點上
     3、找到觸發對象,判斷是否符合要求,如果符合要求,進行後續操作。
     其實事件委託的好處不僅止於此,再來個需求,在頁面上給一個按鈕,通過點擊按鈕,然後給ul標籤新加一個ul標籤.那這個新加的li標籤,也要實現上面兄弟級一樣的功能.傳統事件中,咱們需要爲新加的綁定事件,那不是非常的麻煩嗎.

  //爲了給新加標籤內容標識
   var i = 6;
   var oBtn = document.getElementById("btn1");
   oBtn.onclick = function(){
     //創建一個新的li標籤
     var newLi = document.createElement("li");
     //給新加的標籤添加內容
     newLi.innerHTML = 111 * i++;
     //將新加的li標籤,添加到ul元素的末尾
      oUl.appendChild(newLi);
  }

     我們這裏通過事件委託來實現,上述新加的li標籤,同樣也享受li兄弟級的一樣的功能.那就是後添加節點,擁有前面綁定好的函數。
     事件委託的優點:
      1.提高性能:每一個函數都會佔用內存空間,只需添加一個事件處理程序代理所有事件,所佔用的內存空間更少。
      2.動態監聽:使用事件委託可以自動綁定動態添加的元素,即新增的節點不需要主動添加也可以一樣具有和其他元素一樣的事件。
      那今天的js事件委託就講到這裏了,歡迎各位大佬來噴,評論區留給你們

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章