1.事件委托的作用
事件委托的意义:,事件就是onclick,onmouseover,onmouseout等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件。利用冒泡的原理,把事件加到父级上,触发执行效果。
也就是:利用冒泡的原理,把事件加到父级上,触发执行效果。
2.下面是网上择抄的一个例子:
<ul id="ul"> <li>aaaaaaaa</li> <li>bbbbbbbb</li> <li>cccccccc</li> </ul>
js部分:
window.onload = function(){ 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 = ""; } } }
这样我们就可以做到li上面添加鼠标事件。
但是如果说我们可能有很多个li用for循环的话就比较影响性能。
下面我们可以用事件委托的方式来实现这样的效果。html不变
首先看看在jquery中的写法:
$('#ul').on('mouseover','li',function(){ $(this).css('background','red'); }); $('#ul').on('mouseout','li',function(){ $(this).css('background',''); });
jquery的写法非常简单,快捷,但是jquery写多了,就快连js也忘了怎么写。
window.onload = function(){ var oUl = document.getElementById("ul"); var aLi = oUl.getElementsByTagName("li"); /* 这里要用到事件源:event 对象,事件源,不管在哪个事件中,只要你操作的那个元素就是事件源。 ie:window.event.srcElement 标准下:event.target nodeName:找到元素的标签名 */ oUl.onmouseover = function(ev){ var ev = ev || window.event; var target = ev.target || ev.srcElement; //alert(target.innerHTML); alert(target.nodeName); if(target.nodeName.toLowerCase() == "li"){ target.style.background = "red"; } } oUl.onmouseout = function(ev){ var ev = ev || window.event; var target = ev.target || ev.srcElement; //alert(target.innerHTML); if(target.nodeName.toLowerCase() == "li"){ target.style.background = ""; } } }
3.事件委托说到底是用了target来添加事件处理,但是由于ie永远不按标准走,上面已经对其做了兼容,
ie:window.event.srcElement
标准下:event.target
在这里先说说target与currentTarget的区别
标准情况下,target在事件流的目标阶段;currentTarget在事件流的捕获,目标及冒泡阶段。只有当事件流处在目标阶段的时候,两个的指向才是一样的, 而当处于捕获和冒泡阶段的时候,target指向被单击的对象而currentTarget指向当前事件活动的对象(一般为父级)。
网上的一个例子:
<div id="outer" style="background:#099"> click outer <p id="inner" style="background:#9C0">click inner</p> <br> </div> <script type="text/javascript"> function G(id){ return document.getElementById(id); } function addEvent(obj, ev, handler){ if(window.attachEvent){ obj.attachEvent("on" + ev, handler); }else if(window.addEventListener){ obj.addEventListener(ev, handler, false); } } function test(e){ alert("e.target.tagName : " + e.target.tagName + " e.currentTarget.tagName : " + e.currentTarget.tagName); } var outer = G("outer"); var inner = G("inner"); //addEvent(inner, "click", test); addEvent(outer, "click", test); </script>
上面的示例中,当在outer上点击时,e.target与e.currentTarget是一样的,都是div;当在inner上点击时,e.target是p,而e.currentTarget则是div。
如果在ie中,window.event.srcElement就等于标准下的e.target
那么e.currentTarget呢?IE9之前都不兼容currentTarget
下面是两种兼容方法
1)修改this指针,并在IE下将ad1赋值给event.currentTarget
<a id="ad1" data-at="1" href=""> <span id="span1">demo</span> </a> <script> var ad1 = document.getElementById("ad1"); var addListener = (function() { if(document.attachEvent) { return function(element, event, handler) { element.attachEvent('on' + event, function() { var event = window.event; event.currentTarget = element; event.target = event.srcElement; handler.call(element, event); }); }; } else { return function(element, event, handler) { element.addEventListener(event, handler, false); }; } }()); addListener(ad1,"click",function(e){ var currentTarget = e.currentTarget; var at =0; if(currentTarget.dataset){ at = currentTarget.dataset.at }else{ at = currentTarget.getAttribute("data-at"); } alert(at) }) </script>
2)向上寻找父元素
<script> var ad1 = document.getElementById("ad1"); ad1.onclick = function(e){ var e = e || window.event; var target = e.target || e.srcElement; if(target.tagName.toLowerCase != "a"){ target = target.parentNode } alert(target.id) // ad1 var at = 0; if(target.dataset){ at = target.dataset.at }else{ at = target.getAttribute("data-at"); } } </script>