javascript委托 js事件委托的原理
什么是JS事件委托呢?
首先,我们要明确什么是事件:所谓的事件就是像:onclick,onmouseover,onmouseover.......这些事件,那委托呢?就是指原来发生在这些事件上的元素,加到其它的元素身上来完成。
JS事件委托的原理:就是利用冒泡的原理,把事件加到父级或是父级的父级身上,来触发执行操作。
使用事件委托的优势:1)提高性能;
2)新添加的元素也会有之前加的事件;
下面我们用例子来说明一下:点击改变li的背景颜色
HTML部分:
1 <ul id="ul1">
2 <li></li>
3 <li></li>
4 <li></li>
5 <li></li>
6 <li></li>
7 <li></li>
8 <li></li>
9 <li></li>
10 </ul>
style样式部分:
1 <style>
2 *{ margin:0; padding:0; list-style:none; }
3 ul{ overflow:hidden; }
4 li{ width:100px; height:100px; background:#ccc; float:left; margin:10px; }
5 </style>
<script>部分:
window.onload=function (){
var oUl=document.getElementById('ul1');
var aLi=oUl.getElementsByTagName('li');
for(var i=0; i<aLi.length; i++){
aLi[i].onclick=function (){
this.style.background='red';
};
};
};
上面的例子就是我们常用的普通写法是如上这种写法,但是大家知道如果页面上有n多个li标签,就会循环无数多次,这样对性能的损耗是巨大的,所以这时候我们就可以考虑用事件委托来完成,把onclick事件加到li的父级上去。
事件委托的写法如下:
<script>
window.onload=function (){
var oUl=document.getElementById('ul1');
var aLi=oUl.getElementsByTagName('li');
oUl.onclick=function(){
this.style.background='red';
};
};
</script>
一步操作,省了循环,是不是一下子提高了性能呢?但有些同还可能会问,不对啊,里面的this指向的可是oUl这个元素,不再是指向了aLi[i],是的,你的分析是对的,要想用事件委托做出来跟for循环中一样的效果,我们还必须知道event对象里有一个叫事件源的东西,那什么又是事件源呢?简单讲就是不管在哪个事件中,你操作的那个元素就是事件源,并用它也是有一定的兼容性问题存在的。
在IE,chrome中事件源的获取方法是srcElement 。在FF中事件源的获取方法是target,所以我们还要给它写一个兼容的写法,并且给事件源加样式,就完成了跟for循环一样的效果。
<script>
window.onload=function (){
var oUl=document.getElementById('ul1');
var aLi=oUl.getElementsByTagName('li');
oUl.onclick=function(ev){
var oEvent=ev||event;
var target=oEvent.srcElement||oEvent.target;
target.style.background='red';
};
};
</script>
不过这还不算完,为什么呢?因为有些同学在点页面的时候突然会点到ul的区域,会出现了整个Ul都变红色的情况,那我们肯定是不希望触发ul的这个事件呢,所以还需要进行有效的判断,在这里面我们判断的时候用到了tagName。
<script>
window.onload=function (){
var oUl=document.getElementById('ul1');
var aLi=oUl.getElementsByTagName('li');
oUl.onclick=function(ev){
var oEvent=ev||event; //事件兼容写法。
var target=oEvent.srcElement||oEvent.target; //事件源兼容写法。
if(target.nodeName!='Li') return; //判断如果节点的名字不是LI就返回。
target.style.background='red';
};
};
</script>
好,第一个例子完美了!
下面我们再另外一个例子,来验证它的另外一个优势:新添加的元素也会有之前加的事件。
HTML部分:
<input type="button" value="按钮" id="btn" />
<ul id="ul1">
<li>11111</li>
<li>22222</li>
<li>33333</li>
<li>44444</li>
</ul>
Javascript部分:
<script>
window.onload=function(){
var oBtn=document.getElementById('btn');
var oUl=document.getElementById('ul1');
var aLi=oUl.getElementsByTagName('li');
var iNow=4;
for(var i=0;i<aLi.length;i++){
aLi[i].onmouseover=function(){
this.style.background='red';
};
aLi[i].onmouseout=function(){
this.style.background='';
};
};
oBtn.onclick=function(){
iNow++;
var oLi=document.createElement('li');
oLi.innerHTML=11111*iNow;
oUl.appendChild(oLi);
};
};
</script>
这样的写法上我们可以看到新添加的元素竟然不能跟原来的元素一样,鼠标划过时的底色变色现象。如果改用事件委托的方法的话结果就不一样了。
window.onload=function(){
var oBtn=document.getElementById('btn');
var oUl=document.getElementById('ul1');
var aLi=oUl.getElementsByTagName('li');
var iNow=4;
oUl.onmouseover=function(ev){
var oEvent=ev||event;
var target=oEvent.srcElement||oEvent.target;
if(target.nodeName!='LI') return;
target.style.background='red';
};
oUl.onmouseout=function(ev){
var oEvent=ev||event;
var target=oEvent.srcElement||oEvent.target;
if(target.nodeName!='LI') return;
target.style.background='';
};
oBtn.onclick=function(){
iNow++;
var oLi=document.createElement('li');
oLi.innerHTML=11111*iNow;
oUl.appendChild(oLi);
};
};
</script>