首页 > 代码库 > 论如何做好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互殴时的一条好池鱼之事件绑定篇