我最喜欢的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
//...your event handler
})
现在,当我们点击ul 选择器下的一个匹配的元素.module.complete ,我们传入的函数中的代码将被运行,我们可以从event.target 中提取被点击的项目引用。