事件委托

423 阅读1分钟

一 事件委托

针对特定场景,基于事件冒泡原理实现,将事件委托给祖先元素,从而优化内存或者监听动态元素。

  1. 场景一:给一百个按钮添加点击事件,这个时候若分别给每个按钮添加事件,不仅麻烦且浪费内存。此时就可以利用事件委托机制,将该事件委托给父辈元素,当冒泡的时候,判断一下事件e是哪个按钮的即可。
  2. 场景二:监听目前不存在的点击事件。原理同上,冒泡的时候判断一下事件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而已

四 如何手写一个事件系统?