首页 > 代码库 > 论如何做好IE和Chrome互殴时的一条好池鱼之事件绑定篇
论如何做好IE和Chrome互殴时的一条好池鱼之事件绑定篇
传统方法:
且看下面代码,
function addLoadEvent(func){ var oldload=window.onload; if(typeof window.onload!="function"){ window.onload=func; }else{ window.onload=function(){ oldload(); func(); } } }
至此,使用addLoadEvent方法可以不断地为window.onload事件添加方法。
另外,把这个函数小改一番便可以使用到其他事件上。
DOM 2 提供的新的api
node.addEventListener方法。
具体看代码:
var btn=document.getElementById("btn");//btn是一个按钮 btn.addEventListener("click",doSomething1,false); btn.addEventListener("click",doSomething2,false);
于是,点击btn按钮,会执行两个方法。
貌似问题得到圆满解决,可惜不是。因为IE会跳出来说:“IE没有这个方法”。
在IE上的实现是这个样子的:
var btn=document.getElementById("btn");//btn是一个按钮 btn.attachEvent("onclick",doSomething1); btn.attachEvent("onclick",doSomething2)
功能上完全一样的两个函数,名字不同,参数不同。(注意,addEventListener是“click”,attachEvent是“onclick”)
怒摔。
虽然这是个很容易就解决的问题,但总要被坑一把才能发现。IE和chrome打架真是殃及无数池鱼。
我们聪明机智的程序员总可以用经典思路去解决这种“经典问题”:
function addEventLoad(node,func){ if(node.addEventListener){ node.addEventListener("click",func,false); } if(node.attachEvent){ node.attachEvent("onclick",func); } }
或者再进一步:
function addEventLoad(object,eventName,func){ if(object.addEventListener){ object.addEventListener(eventName,func,false); } if(object.attachEvent){ object.attachEvent("on"+eventName,func); } }
继续深入(重要)
看看btn的代码:
<button id="btn" title="this is a button">btn</button>
然后是两个事件函数的代码:
function do1(){ alert(this.title); } function do2(){ alert(this.title); }
然后放出整个测试页面的代码:
<!DOCTYPE HTML> <html> <head> <script> window.onload=function(){ var btn=document.getElementById("btn"); btn.onclick=function(){ alert("btn1"); }; addEventLoad(btn,do1); addEventLoad(btn,do2); } function addEventLoad(node,func){ if(node.addEventListener){ node.addEventListener("click",func,false); } if(node.attachEvent){ node.attachEvent("onclick",func); } } function do1(){ alert(this.title); } function do2(){ alert(this.title); } </script> </head> <body> <button id="btn" title="this is a button">btn</button> </body> </html>
此页面在chrome上运行,点击按钮会弹出3个警告框,分别是:
“btn1”,“this is a button”,“this is a button”
但在IE上运行则是:
“btn1”,“undefined”,“undefined”
IE虐我千百遍。
经查阅:IE没有实现DOM Level 2(比如document.addEventListener就属于DOM Level 2)。IE有自己的事件处理框架。所以在IE中,事件处理函数为这个事件框架所有,而不属于XHMLT页面上通过点击事件或鼠标移动事件激活的一个对象。也就是说,do1和do2中的this关键字,在chrome中就是指那个按钮,在IE中就是指IE事件框架。
至此,看起来问题难以解决,真是绝望。
但其实所谓天无绝人之路,其实,事件处理程序会从attachEvent()和addEventListener()得到一个Event对象,这个对象有两个很有用的属性:
“type”:提供所触发事件的事件名,比如“click”
“target”:指向事件的目标,即页面上被激活的对象
然后,我们发现问题又来了:chrome和ie的这个Event对象是不同的。在chrome中Event对象的target,在ie中则是srcElement。
但这难不倒我们,看下列函数:
function getActiveObject(e){ var obj; if(!e){ //较早版本的IE不会发送这个对象 obj=window.event.srcElement; }else if(e.srcElement){ obj=e.srcElement; }else{ obj.e.target; } return obj; }
其中e就是那个Event对象。
另外,为了让事件处理函数使用这个Event对象,我们需要在其参数列表上加一个变量,比如这样
do1(e){}
然后我们看看经过修改的完整测试页面:
<!DOCTYPE HTML> <html> <head> <script> window.onload=function(){ var btn=document.getElementById("btn"); btn.onclick=function(){ alert("btn1"); }; addEventLoad(btn,do1); addEventLoad(btn,do2); } function addEventLoad(node,func){ if(node.addEventListener){ node.addEventListener("click",func,false); } if(node.attachEvent){ node.attachEvent("onclick",func); } } function do1(e){ var obj=getActiveObject(e) alert(obj.title); } function do2(e){ var obj=getActiveObject(e) alert(obj.title); } function getActiveObject(e){ var obj; if(!e){ //较早版本的IE不会发送这个对象 obj=window.event.srcElement; }else if(e.srcElement){ obj=e.srcElement; }else{ obj.e.target; } return obj; } </script> </head> <body> <button id="btn" title="this is a button">btn</button> </body> </html>
至此,此页面在Chrom和IE上都可以得到想要的东西。
论如何做好IE和Chrome互殴时的一条好池鱼之事件绑定篇