什么是事件委托?

184 阅读1分钟

事件委托是利用事件冒泡原理,让节点的父级代为执行事件。而不需要循环遍历元素的子节点

·优点

√ 省监听数(内存)

√ 可以监听动态元素

·场景一

你要给100个按钮添加点击事件,咋办?

答:监听这100个按钮的父级,等冒泡的时候判断event.target的值是不是这100个按钮中的一个

·场景二

你要监听目前不存在的元素的点击事件,咋办?

答:监听父级,等点击的时候看看是不是要监听的元素即可

下面使用函数进行封装的一段代码,使用envent.target判断是否匹配目标选择器,示例:


<html>
<head>
  <meta charset="utf-8">
  <title>title</title>
</head>
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
 <script>
    on('click','ul','li',()=>{
       console.log('li 被点击了')
    })
    function on(eventType,element,selector,fn){
      if(!(element instanceof Element)){
      //if判断参数传入的element是否为Element元素,如果是ID名或类名则进行获取对应名称的元素
          element=document.querySelector(element)
      }
      element.addEventListener(eventType,(e)=>{
          const t=e.target
          if(t.matches(selector)){ // maches判断选择器是否匹配 
          return fn(e)
          }
   })
}
 </script>
</body>
</html>

·场景三

上述场景二存在问题:li里面存在span元素,点击span元素不是当前监听的目标li元素,不会触发函数。

解决:那么这样的话应该遍历父节点是否存在li元素,直到遍历到ul为止。 示例:


<html>
<head>
  <meta charset="utf-8">
  <title>title</title>
</head>
<body>
    <ul>
        <li>1</li>
        <li><span>2</span></li>
        <li>3</li>
    </ul>
 <script>
    function on(eventType,element,selector,fn){
      element.addEventListener(eventType,e=>{
        let el=e.target
        // maches判断选择器是否匹配
        while(!el.matches(selector)){
        //如果一直遍历父元素到事件委托的元素为止则证明没有目标元素
          if(el===element){
            el=null //让el为空结束循环
            break
          }
          el=el.parentNode
        }
        //el不为空执行fn
        el&&fn.call(el,e,el)
      })
      return element
    }
    on('click','ul','li',(e)=>{console.log(e.target.innerHTML)})
 </script>
</body>
</html>