DOM事件與事件委託

DOM事件模型與事件委託

DOM事件模型

捕獲與冒泡

事件冒泡和捕捉是兩種機制,主要描述當在一個元素上有兩個相同類型的事件處理器被激活會發生什麼。

當一個事件發生在具備父元素的元素上:html

捕獲

在捕獲階段:瀏覽器

  • 瀏覽器檢查元素的最外層祖先<html>,是否在捕獲階段中註冊了一個onclick事件處理程序,若是是,則運行它。
  • 而後,它移動到<html>中單擊元素的下一個祖先元素,並執行相同的操做,而後是單擊元素再下一個祖先元素,依此類推,直到到達實際點擊的元素。

冒泡

在冒泡階段,偏偏相反:bash

  • 瀏覽器檢查實際點擊的元素是否在冒泡階段中註冊了一個onclick事件處理程序,若是是,則運行它
  • 而後它移動到下一個直接的祖先元素,並作一樣的事情,而後是下一個,等等,直到它到達<html>元素。

示意圖

事件捕獲vs事件冒泡

當事件捕獲和事件冒泡一塊兒存在的狀況,事件又是如何觸發呢。
這裏記被點擊的DOM節點爲target節點

app

  1. document 往 target節點,捕獲前進,遇到註冊的捕獲事件當即觸發執行
  2. 到達target節點,觸發事件(對於target節點上,是先捕獲仍是先冒泡則捕獲事件和冒泡事件的註冊順序,先註冊先執行)
  3. target節點 往 document 方向,冒泡前進,遇到註冊的冒泡事件當即觸發

    總結就是:
  • 對於非target節點則先執行捕獲在執行冒泡
  • 對於target節點則是先執行先註冊的事件,不管冒泡仍是捕獲
  • 對於事件代理來講,在事件捕獲或者事件冒泡階段處理並無明顯的優劣之分,可是因爲事件冒泡的事件流模型被全部主流的瀏覽器兼容,從兼容性角度來講仍是建議你們使用事件冒泡模型。

addEventListener()

W3C給瀏覽器提供了一個函數 - addEventListener函數

  • 事件綁定API
    IE5*:baba.attachEvent('onclick',fn) //冒泡
    網景:baba.addEventListener('click',fn) //捕獲
    W3C:baba.addEventListener('click',fn,bool)
  • 若是bool不傳或爲falsy
    就讓fn走冒泡,即當前瀏覽器在冒泡階段發現babafn監聽函數,就會調用fn,並提供事件信息
  • 若是booltrue
    就讓fn走捕獲,即當瀏覽器在捕獲階段發現babafn監聽函數,就會調用fn,並提供事件信息

事件委託

冒泡還容許咱們利用事件委託——這個概念依賴於這樣一個事實,若是你想要在大量子元素中單擊任何一個均可以運行一段代碼,能夠將事件監聽器設置在其父節點上,並讓子節點上發生的事件冒泡到父節點上,而不是每一個子節點單獨設置事件監聽器。ui

舉例1:

你要給多個按鈕添加點擊事件spa

<div id="div1">
<button>click 1</button>
<button>click 2</button>
<button>click 3</button>
<button>click 4</button>
<button>click 5</button>
<button>click 6</button>
<button>click 7</button>
<button>click 8</button>
<button>click 9</button>
</div>
複製代碼

監聽這些按鈕的祖先,等冒泡的時候判斷target是否是這寫按鈕中的一個代理

div.addEventListener('click',(e)=>{
    const t = e.target
    if(t.tagName.toLowerCase() === 'button'){
        console.log('button 被點擊了')
    }
})
複製代碼

舉例2:

你要監聽目前不存在的元素的點擊事件code

<div id="div1">

</div>
複製代碼

監聽祖先元素,等點擊的時候看看是否是我想要監聽的元素便可cdn

setTimeout(()=>{
const button = document.creatElement('button')
button.textContent = 'click 1'
div1.appendChild(button)
    },1000)
    
div1.addEventListener('click',(e)=>{
    const t =e.target
    if(t.tagName.toLowerCase() === 'button'){
        console.log('button 被 click')
    }
})
複製代碼

封裝事件委託

function on(eventType,element,selector, fn){
    if(!(element instanceof  Element)){
        element = document.querySelector(element)
    }
    element.addEventListener(evenType,(e)=>{
        const t = e.targer
        if(t.matches(selector)){
            fn(e)
        }
    })
}
複製代碼
相關文章
相關標籤/搜索