先讲我看到的一篇文章中对事件委托的解释,找不到了,不过还是感谢他的例子:
你在公司上班,快件是你们员工一起在门口等着签收,还是让前台帮签收(委托事件,更高效的解决办法)?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);
}
完。欢迎指正错误及完善总结。