一 事件委托
针对特定场景,基于事件冒泡原理实现,将事件委托给祖先元素,从而优化内存或者监听动态元素。
- 场景一:给一百个按钮添加点击事件,这个时候若分别给每个按钮添加事件,不仅麻烦且浪费内存。此时就可以利用事件委托机制,将该事件委托给父辈元素,当冒泡的时候,判断一下事件e是哪个按钮的即可。
- 场景二:监听目前不存在的点击事件。原理同上,冒泡的时候判断一下事件e。
<div id="parent">
一秒后添加新button
</div>
const parent=document.querySelector('#parent');
setTimeout(()=>{
const button =document.createElement('button');
parent.appendChild(button);
},1000)
parent.addEventListener('click',(e)=>{
const t=e.target;
if(t.tagName.toLowerCase()==='button'){
console.log('button被click了');
}
})
二 封装事件委托
//判断target是否匹配selector
function on(eventType, element, selector, fn) {
if(!(element instanceof Element)){
element=document.querySelect(element);
}
element.addEventListener(eventType,(e)=>{
const t=e.target;
if(t.matches(selector)){
fn(e);
}
})
}
//如果button中嵌套一个span,此时点击按钮,e.target是span,那么不会调用fn
//正确方法,递归判断e.target是否匹配selector以及selector的祖先元素
function on(eventType, element, selector, fn) {
if(!(element instanceof Element)){
element=document.querySelect(element);
}
element.addEventListener(eventType, e => {
let el = e.target
while (!el.matches(selector)) {
if (element === el) {
el = null
break
}
el = el.parentNode
}
el && fn.call(el, e, el)
})
return element
}
三 JS支持事件吗?
浏览器提供的DOM功能,JS只是调用了DOM提供的addEventListener而已