委托事件,事件冒泡,事件捕获,this,target总结

本文通过一个生动的例子解释了事件委托的概念及其优势,包括提高运行效率和确保动态添加元素也能响应事件。并通过三种不同的实现方法(直接绑定、jQuery绑定、事件委托)进行对比,展示了事件委托在处理大量动态内容时的高效性和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先讲我看到的一篇文章中对事件委托的解释,找不到了,不过还是感谢他的例子:
你在公司上班,快件是你们员工一起在门口等着签收,还是让前台帮签收(委托事件,更高效的解决办法)?50人的公司看不出来高效差距,那5000人的公司呢?
1,委托事件:依托于事件冒泡原理让自己的父级或祖籍(甚至根元素)来帮自己做某些事情。
优点:
A:提高运行效率(尤其对于需要循环操作的列表);
B:动态添加后的元素,仍然可以有这些事件(对比与给自己添加的事件,后续动态添加时,新来的这些元素不会有这些事件)
例子:给列表li添加事件,并保证动态添加的元素都有该事件。
html代码:

<ul id="ul">
   <li>1</li>
   <li>2</li>
   <li>3</li>
 </ul>

js给li加事件(第一种方法):

 var oUl = document.getElementById("ul");
 var aLi = oUl.getElementsByTagName("li");

 for(var i=0; i<aLi.length; i++){
       aLi[i].onmouseover = function(){
             this.style.background = "red";
   }
   aLi[i].onmouseout = function(){
         this.style.background = "";
   }
 }

或者jquery去写(第二种方法):

$('li').on("mouseover",function(){
                          $(this).css("background","red").siblings().css("background","");
 })

或者使用委托事件去写:
js委托事件(第三种方法)

oUl.onmouseover=function(ev){
      var ev=ev||window.event;
      var target=ev.target||ev.srcElement;
      // 冒泡事件中target指向触发事件的元素(先li后ul),后面会详细说明,所以下面的判断必不可少
      if(target.nodeName.toLowerCase()=="li")//DOM节点名都是大写
      target.style.background="red";
      console.log(target);    
 }
 oUl.onmouseout=function(ev){
       var ev=ev||window.event;//做兼容
       var target=ev.target||ev.srcElement;//做兼容srcElement是IE下的
       if(target.nodeName.toLowerCase()=="li")
       target.style.background=""; 
 }

这三种方法都可以处理问题的前半部分,但是运行效率和稳健性却是最后一个最好。
对于动态添加的li:
为了方便,我们加个button,点击一次就添加一个li
第一种方法的后续

var num=3;
oBtn.onclick = function(){
      var oLi = document.createElement("li");
      oLi.innerHTML = num;
      oUl.appendChild(oLi);
      num ++;
 }

juery的后续(第二种方法自己去写很简单)
然后发现,新加的li没有事件,鼠标触发时,不会有任何改变,因为,所有事件li都已经在for循环中完了。
在委托事件中,绑定事件的是个固定元素ul,so。
委托事件中加入后续代码(这部分代码都一样)

var num=3;
oBtn.onclick = function(){
      var oLi = document.createElement("li");
      oLi.innerHTML = num;
      oUl.appendChild(oLi);
      num ++;
 }

委托事件中涉及到三个知识点:
A:事件冒泡(对应事件捕获);
B:js中的this,event.target,event.currentTarget
C:衍生知识点:jquery中的 (this) (event.target),$(event.currentTarget)
A:如上案例是事件冒泡(默认状态下)无论你给谁绑定事件,但触发事件是由内而外的,比较常用。与他对应的是事件捕获,由外而内的触发事件,二者怎么转换呢(注意:产生这两者的前提是,给每一个元素都要先绑定事件,而不是只绑定一个元素,它就会发生冒泡事件):
addEventListener有三个参数,最后一个默认为false就是冒泡事件。

document.getElementById("ul").addEventListener("click",function(e){
   console.log("被触发的元素,"+this.nodeName);
    })
    document.getElementsByTagName("li")[0].addEventListener("click",function(e){
   console.log("被触发的元素,"+this.nodeName);
    })

当点击第一个li时,打印顺序是LI-UL(事件冒泡有内而外)
修改为true后

document.getElementById("ul").addEventListener("click",function(e){
   console.log("被触发的元素,"+this.nodeName);
    },true)
    document.getElementsByTagName("li")[0].addEventListener("click",function(e){
   console.log("被触发的元素,"+this.nodeName);
    },true)

当点击第一个li时,打印顺序是UL-LI(事件捕获有外而内)
一般都使用默认状态下的,也就是冒泡事件。
B:
1>首先js中的this,event.target,event.currentTarget和jquery中的 (this) (event.target),(前面的$不显示哎!!!!)各自所指代的都是内容不变只是获取方式不同,获取到后的命名不同,前者是dom,后续能用js方法处理,后者是jquery对象,后续能用jquery方法处理
2>相关关键词的兼容性,在js中的event和target都需要做兼容

var ev=ev||window.event;//做兼容
var target=ev.target||ev.srcElement;//做兼容srcElement是IE下的

在jquery中一个on就处理了所有兼容,直接使用

$('li').on("mouseover",function(event){
        console(event.target);
    })

3>this,event.target,event.currentTarget三者个指代谁?
前提先理解:触发事件的元素和绑定事件的元素完全不是同一个元素,只有当鼠标放在绑定事件的元素身上时,他俩才指代一个东西。
超容易理解的:
这里面有一个相对论的结论:
1,当同时给li和ul都绑定事件,this指的是各自绑定事件的元素(ul或li,相对来说是变化的),targrt指的都是是触发事件的元素(相对来说是不变的),

$('li').on('click',function(e){
    console.log("找target"+e.target);
    console.log("找currentTarget"+e.currentTarget);
    console.log("找"+this);
})
$('ul').on('click',function(e){
    console.log("找target"+e.target);
    console.log("找currentTarget"+e.currentTarget);
    console.log("找"+this);
})

2,当只给ul添加绑定事件,(单独加事件时只能给父级,要给li加就必须是全加绑定事件才有效果)
A:触发li时,this指的还是绑定事件的ul,target指的是触发事件的li,B:当触发ul时,this还是指代绑定事件的ul(想对这一层意义来说this不变),而target指的是触发事件的ul(发生了改变)
this指的是绑定事件的对象。(绑定在ul上指的就是ul,绑定在li上,指的就是li)

$('ul').on('click',function(e){
    console.log("找target"+e.target);
    console.log("找currentTarget"+e.currentTarget);
    console.log("找"+this);
})

event.target指的触发该事件的元素。(鼠标放在li上就是li,放在ul上就是ul)
总结:this永远指向绑定事件的元素,target永远指向触发事件的元素。
不要再用变与不变来解释this和target,都是相对的。
event.currentTarget存在于冒泡过程中:哪个元素的监听器触发了事件
衍生一个获取函数

function getEventTrigger(event)
  { 
  x=event.currentTarget; 
  alert("谁的监听器触发了事件"
  + x.id);
  }

完。欢迎指正错误及完善总结。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值