事件委托
好处:
- 节省监听器(假设ul有100个li,如果不用事件委托,则需要一百个监听器,事件委托就可以只需要ul一个监听器)
- 动态监听、(比如说ul里面现在是空的,没有li,如何添加事件监听?只能事件委托,等到加载了li,点击的时候照样会触发监听器) 坏处:
- 调试的时候不知道当前元素有哪些事件监听 如何解决: 用Chrome的调试,有eventlistener可以看。
错误版(但是有可能通过面试)
ul.addEventListner('click',function(e){
if(e.target.tagName.toLowerCase()==='li'){
fn()//执行某个函数
}
}
e.target和e.currentTarget的区别是,e.target是用户触发事件的对象,e.currentTarget是监听的对象,e.target是会变的,e.currentTarget是不会变的
vue现在会自动实现事件委托,所以基本用不上,但是面试会问。
错在哪里?
如果用户点击的是li里面的span,就没法触发fn,这显然不对
高级版
function delegate(element, eventType, selector, fn){
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
}
delegate(ul, 'click', 'li', f1)
思路是点击span后,遍历span的祖先元素,看其中有没有ul里面的li