js事件委託詳解

先說事件流

js的事件流分爲3個階段:捕獲、目標、冒泡。即事件來了,先從上到下傳播(捕獲),到達目標節點(目標),而後在往上傳播(冒泡)。看下圖:html

圖片描述

咱們能夠在綁定事件的時候指定指是在哪一個階段觸發事件,element.addEventListener(event, function, useCapture),useCapture默認爲false,即默認在冒泡階段觸發事件,來作個測試:node

demo長這樣:
圖片描述函數

html:性能

<div id='wraper'>
        wraper
        <ul>
            <li>li1</li>
            <li>li2</li>
            <li id='li3'>
                li3
                <span>span</span>
            </li>
        </ul>
    </div>

js:測試

document.getElementById('wraper').addEventListener('click',function(e){
    console.log('wraper')
},false)

document.getElementById('li3').addEventListener('click',function(e){
    console.log('li3')
},false)

document.getElementsByTagName('span')[0].addEventListener('click',function(){
    console.log('span')
},false)

能夠看到,這裏全是在冒泡階段觸發事件,所以結果爲:span li3 wraper 這樣的順序(從下到上),以此類推,若是所有設置爲捕獲階段觸發事件呢?順序確定就反過來了,繼續看下面:優化

document.getElementById('wraper').addEventListener('click',function(e){
    console.log('wraper')
},true)

document.getElementById('li3').addEventListener('click',function(e){
    console.log('li3')
},true)

document.getElementsByTagName('span')[0].addEventListener('click',function(){
    console.log('span')
},true)

結果爲:wraper li3 span
同時還能夠測試,某一個事件在捕獲階段是優先觸發於冒泡階段的:spa

document.getElementById('wraper').addEventListener('click',function(e){
    console.log('wraper')
},false)

document.getElementById('li3').addEventListener('click',function(e){
    console.log('li3')
},true)

document.getElementsByTagName('span')[0].addEventListener('click',function(){
    console.log('span')
},false)

結果爲:li3 span wrapercode

從需求出發

來了這樣一個需求:在上面的demo中,要給ul下的每一個li綁定一個事件,在點擊以後觸發。
若是是每一個li都去單獨綁定事件?明顯不科學,畢竟去拿li列表也是畢竟消耗性能的,同時每一個事件綁定的回調函數也會佔用大量的內存。
你可能會說,個人元素很少,上面的消耗無所謂。那若是有動態插入的元素呢?
因而委託就能夠用上了。htm

document.getElementById('wraper').addEventListener('click', function (e) {
  var target = e.target
  if (target.nodeName.toLocaleLowerCase() === 'li') {
    console.log(target.innerHTML);
  }
});

這裏的e.target指的時候鼠標最後點擊的元素。在這個demo中,點擊深紅色的span,e.target就指的是span,若是點擊li3且不在紅色的span中,那麼e.target指li3。
有一個問題就是若是匹配的元素須要更具體一些,好比class爲li-test的某個li,就須要作優化處理了。後面專門來一篇文章講。blog

相關文章
相關標籤/搜索