js的事件委托

1,299 阅读4分钟

前言.一听js事件委托心里面还是有点模糊的,之前只听说过事件捕获和事件冒泡,于是我提出了2个疑问?(1).什么是事件委托,(2).事件委托能解决什么事情

回顾事件捕获和事件冒泡,先举个小例子,看看下面的div层级结构d1包裹d2,d2包裹d3,假设我为这3个元素分别绑定点击事件,当点击d3元素会触发它的父元素吗?

 <div class="d1"> 我是d1 

 <div class="d2">我是d2 

 <div class="d3">我是d3</div> 

 </div> 

 </div>

绑定事件内容如下

 let d1=document.getElementsByClassName("d1")[0];  
 let d2=document.getElementsByClassName("d2")[0];  
 let d3=document.getElementsByClassName("d3")[0];
	
	d1.onclick=function(){
		 console.log("我是d1");
	}
	
	d2.onclick=function(){
		 console.log("我是d2");
	}
		
	d3.onclick=function(){
		 console.log("我是d3");
	}

点击d3元素的结果如下

很显然点击d3是触发了它的父元素,这是为什么呢?是因为事件冒泡机制,当触发d3的点击事件时会由内而外的触发它的父元素的点击事件,就像泡泡从水底慢慢往水面冒泡一样,而事件捕获呢恰好是与事件冒泡是相反的,当触发子元素时会先触发它的父元素事件,然后再触发子元素的事件,这个过程是由外而内的


事件委托例子:事件委托是依托于事件冒泡机制的,假设有如下层级,现在ul中只有2个li,如果为2个li绑定事件是消耗不了多少性能的,

可是如果有1千个或更多li呢?难道都要一个一个去为他们绑定事件吗?当li事件数量越多时为它们绑定事件的消耗也越多,意思就是绑定的事件越多dom消耗也越多。于是事件委托就出来了,

事件委托就是将相同节点的同一事件类型委托给父元素,由父元素来处理子元素的事件。举个例子当点击第一个li时会触发父元素,点击第二个li时也会触发元素,无论多少个li都是会触发父元素,那就不用为所有li绑定点击事件了,这种做法能有效的减少dom操作

<ul>
   <li>1</li>
   <li>2</li>
   .....
</ul>

怎么做?

首先呢我们应该了解一个api,通过addEventListener(eventType,listener,useCapture)可以为元素绑定事件

addEventListener(eventType,listener,useCapture)参数解析

eventType:需要绑定的事件类型,必选,类型为string,例子:click

listener:事件触发的函数,必选,类型为function

useCapture:表示事件是否发生在捕获阶段,可选,默认false,表示事件发生在冒泡阶段

 <ul class="ul1">
	<li>1</li>
	<li>2</li>
	<li>3</li>
 </ul>
  /**js代码*/
  let ul1=document.getElementsByClassName("ul1")[0];
	 //为ul1绑定事件
          ul1.addEventListener("click",function(e){
	      let event=e || window.event;
	       //获取目标元素
	       let target=event.target || event.srcElement;
	       //target.nodeName是获取目标元素标签,默认是大写,我转成小写了
	       if(target.nodeName.toLowerCase() ==="li"){
                   //打印点击目标元素的内容
	       	   console.log(target.innerHTML);
	       	   }
	    });



当点击第一个li时会触发ul的click事件,然后判断当前点击元素的标签是不是li标签,是的话就打印这个元素的内容,所以控制台打印的是1,但是我并未给第一个li绑定事件,li事件都委托ul来处理了

又有一个提问,如果新增一个li事件是否还能动态的委托给父元素呢?


第一步点击添加li按钮,点击后ul多了一个元素,然后点击ul中的第四个li元素,发现控制台还是能正常打印出来,说明新增的元素事件也可以委托给父元素

奈何我的文化有限,并不能深度解析事件委托......


总结:

事件委托的作用:(1)能大大减少内存操作, (2)动态的绑定事件

事件委托的局限性:一件事情并不是10全10美,比如 focus、blur 之类的事件本身没有事件冒泡机制,所以无法委托;

mousemove、mouseout 这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,因此也是不适合于事件委托的