原生 JS 实现事件委托

什么是事件委托

事件委托是利用事件的冒泡原理来实现的,何为事件冒泡呢?就是事件从最深的节点开始,然后逐步向上传播事件,举个例子:页面上有这么一个节点树,div>ul>li>a;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,那么我们给最外面的div加点击事件,那么里面的ul,li,a做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。

那么为什么需要事件委托呢?

假设我们有一个ul ul里有两个li 我们需要给这两个li添加点击事件 那么我们可能会使用addEventListener 进行监听 添加点击事件 如果li有很多呢 给每一个li添加点击事件 那就会相当的麻烦 当然 你也许很有耐心 但是如果我们想给li动态的添加 那么新添加的li是不会被监听到的。

那我们使用for循环,给每个li添加点击事件呢? 如果li数量很多 这样的话每一次循环都需要创建一个监听器并占用一定的内存,性能会变的很差,所以我们只需要给li的父元素添加一个监听器 就可以达到相同的效果,并且性能会有所提高。

实现

   
var ul=document.querySelector("ul");
ul.addEventListener('click',function(){
  console.log('ok');
})

这样我们点击li时就会执行里面的代码 但是当我们点击ul内部但不是li的区域 还是会触发代码执行 所以我们需要判断点击的标签名是否正确再执行代码

var ul=document.querySelector("ul");
ul.addEventListener('click',function(e){
  if(e.target.nodeName==='LI'){
    console.log('ok');
  }
})

这样上面的问题就解决 但是这样就会引发另一个问题 当li存在子元素并且点击li里面的元素时,是不会执行代码的 所以我们需要再次修改

var ul=document.querySelector("ul");
ul.addEventListener('click',function(e){
  var ele=e.target;
  while(ele.nodeName!=='LI'){
    if(ele===ul){
      ele=null;
      break;
    }
    ele=ele.parentNode;
  }
  if(ele){
    console.log('ok');
  }else{
    console.log('no')
  }
})

将当前点击的元素存到ele变量中,判断ele是否是ul如果是则说明并没有点击li或者li内部的元素 所以将ele赋值为空并且退出循环,如果不是ul将ele赋值为ele的父元素再次循环进行判断。

你可能感兴趣的:(原生 JS 实现事件委托)