事件委托

411 阅读2分钟

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。

1. 使用场景

  • 给多个按钮添加点击事件
  • 监听目前还没创建出来的元素的点击事件

第一个场景,可以监听这100个按钮的父层或者更外层元素,等冒泡阶段的时候判断target是不是这100个按钮中的一个。

第二个场景,监听父层或者更外层元素,等点击的时候看看是否是自己想要监听的元素

使用事件委托的好处:

  • 不需要为每个事件创建监听器,省内存
  • 可以动态的监听元素

2. 封装事件委托

on('click','#div1','button',()=>{
    console.log('button 被点击')
})

function on(eventType,element,seletor,fn){
    if(!(element instanceof Element)){
    element = document.querySelector(element)
}
element.addEventListener(eventType,(e)=>{
   const t = e.target
    if(t.matches(selector)){
    fn(e)
     }
  })
}

以上的例子就是一个封装好的事件委托函数,接下来只要用点击button,就会执行on。

思路:给元素添加一个监听,接下来判断当前的target是否满足selector,如果满足就调用函数,不满足就跳过。

**注意:这种方法,在某些情况下时会失效,当button里还有span元素时,事件监听就会失效。**因为当前的target已经由button变为span,所以会失效。

function(eventType,element, selector, fn) {
    if(!(element instanceof Element)){
    element = document.querySelector(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
  },

把代码改成上面的就是最终形态,完美的事件委托。

思路:首先看被操作的元素是否满足button,不符合的话就让该元素等于他的父元素,当找到他的最顶层元素还没找到,就当找不到了,直接结束。如果找到一个父元素匹配选择器,那么事件成立,直接调用函数fn