DOM手写事件委托

96 阅读1分钟

事件委托

好处:

  1. 节省监听器(假设ul有100个li,如果不用事件委托,则需要一百个监听器,事件委托就可以只需要ul一个监听器)
  2. 动态监听、(比如说ul里面现在是空的,没有li,如何添加事件监听?只能事件委托,等到加载了li,点击的时候照样会触发监听器) 坏处:
  3. 调试的时候不知道当前元素有哪些事件监听 如何解决: 用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