js事件委託總結
補充一直沒寫的總結:eyes:當簡單回顧咯
DOM事件流
DOM事件流包括三個階段:事件捕獲階段,處於目標階段與事件冒泡階段
即比如點選td元素時,由外至內層會經歷捕獲階段,目標階段,冒泡階段三個階段,相應地會觸發路徑元素上的事件
此外,addEventListener(type, listener[, useCapture])函式預設設定在冒泡階段,路徑元素的事件才會觸發,此引數為可選值,預設值為false,示例程式碼一併標出
示例程式碼:
<div id="grandFather" style="width: 700px;height: 700px; background-color: red"> <p>grandFather</p> <div id="father1" style="width: 300px; height: 300px; background-color: pink"> <p>father1</p> <div id="son1" style="width: 100px; height: 100px; background-color: yellow"> <p>son1</p> </div> </div> <div id="father2" style="width: 300px;height: 300px; background-color: green"> <p>father2</p> </div> </div> <script type="text/javascript"> let grandFather = document.getElementById('grandFather'), father1 = document.getElementById('father1'), son1 = document.getElementById('son1'), father2 = document.getElementById('father2'); grandFather.addEventListener('click', function(event){console.log('I am grandFather')},true); father1.addEventListener('click', function(event){console.log('I am father1')},false); son1.addEventListener('click', function(event){console.log('I am son1')},false); father2.addEventListener('click', function(event){console.log('I am father2')},false); </script>
點選son1 div時,會冒泡觸發father1與grandFather事件
若將grandFather的use capture引數改為true,則會相應改變執行順序
grandFather.addEventListener('click', function(event){console.log('I am grandFather')},true);
以上是事件流的簡單總結,下面事件委託是對事件冒泡的應用
事件委託
如果在需要有多個DOM事件需要監聽的情況下(比如幾百條微博點選事件註冊),給每一個DOM都繫結監聽函式,對效能會有極大的影響,因此,有一解決方案為事件委託。
事件委託利用了 事件冒泡
與 event.target
event.currentTarget與event.target
currentTarget:表示此事件繫結的元素
target:通俗理解為表示觸發一系列事件的源頭
我們再次修改grandFather的監聽函式
grandFather.addEventListener('click', function(event){ console.log('I am grandFather!!!') console.log('currentTarget:'); console.log(event.currentTarget); console.log('target:'); console.log(event.target);},false); //這裡已改回false
再次點選son1,進入grandFather的監聽函式後顯示如下
事件委託具體步驟
瞭解冒泡與target後,不難可以想到若是在幾百個dom監聽之中,只需把監聽函式繫結在父容器上即可,這裡依舊拿這個簡單的例子修改,我們要做的是點選某個div便顯示列印'I am xxx'
首先,給div都繫結自定義的 data-name
屬性
<!-- 沒有給p元素設定data-name,點選p元素時會顯示data-name為null --> <div id="grandFather" data-name="grandFather" style="width: 700px;height: 700px; background-color: red"> <p>grandFather</p> <div id="father1" data-name="father1" style="width: 300px; height: 300px; background-color: pink"> <p>father1</p> <div id="son1" data-name="son1" style="width: 100px; height: 100px; background-color: yellow"> <p>son1</p> </div> </div> <div id="father2" data-name="father2" style="width: 300px;height: 300px; background-color: green"> <p>father2</p> </div> </div>
接著改寫grandFather的監聽函式
grandFather.addEventListener('click', function(event){ console.log('I am ' + event.target.getAttribute('data-name')); },false); //這些可以註釋掉了! // father1.addEventListener('click', function(event){console.log('I am father1')},false); // son1.addEventListener('click', function(event){console.log('I am son1')},false); // father2.addEventListener('click', function(event){console.log('I am father2')},false);
這樣子就是一個簡單的委託,更多的應用可以結合switch等等