在 jQuery 中,我最喜歡的功能之一就是事件委派。特別是.on()
方法。
我們先選擇一個 DOM 元素,然後使用.on()
來附加一個事件處理程序,該處理程序將在該元素的特定子元素上執行。
為什麼這很有用?因為如果你動態地將元素添加到 DOM 中,通過.on()
注册的單個事件監聽器將對所有子元素都有效,包括在註冊事件處理程序之後添加到 DOM 中的子元素。
假設你有一個表格。在表格內部,我們有一組行,每個行都有一個帶有點擊處理程序的按鈕。
在 DOM 加載時,你註冊一個事件監聽器:
document.addEventListener('DOMContentLoaded', () => {
const buttons = document.querySelectorAll('button')
for (const button of buttons) {
button.addEventListener(...)
}
})
但如果我們向表格中添加一個新的行,我們還必須記得註冊一個新的事件監聽器。
那麼我們如何使用原生 JavaScript 實現相同的功能呢?
我們可以創建一個 on
函數,該函數接受三個參數:包裹元素的選擇器,事件類型(例如 'click'
字符串),以及子元素的選擇器字符串,用於匹配包裹元素的後代元素。在這個函數中,我們首先創建一個循環,然後對每個與我們的包裹元素選擇器匹配的元素添加事件監聽器(因此它可以應用於多個包裹元素)。
然後,如果事件的目標與我們的子元素選擇器(函數的第三個參數)匹配,我們調用作為第四個參數傳遞的回調函數,並將事件作為參數傳遞:
const on = (selector, eventType, childSelector, eventHandler) => {
const elements = document.querySelectorAll(selector)
for (element of elements) {
element.addEventListener(eventType, eventOnElement => {
if (eventOnElement.target.matches(childSelector)) {
eventHandler(eventOnElement)
}
})
}
}
這是我們如何調用這個函數:
on('ul', 'click', '.module.complete', event => {
const item = event.target
//...你的事件處理程序
})
現在,當我們點擊匹配 ul
選擇器下的.module.complete
元素時,我們傳遞的函數中的代碼將被執行,並且我們可以從event.target
中提取被點擊的項目的引用。