欢迎来到 jackNEss'窝窝
I like simple mind

深入剖析事件的绑定与解除

2011年09月25日

谈到 javascript 在日常开发中的应用,最常用就是对DOM的操作,而在与用户进行交互的过程中,离不开事件的绑定(选项卡、手风琴效果、slide框,走马灯效果等),有时候还要用到解除对绑定事件。在这篇文章中,我们就稍微深入地探讨一下事件的绑定与解除

事件绑定

在 javascript 中 对于事件的绑定有5种方式:

1.直接在标签上添加 事件如 onclick = “alert(‘hello world’)”:

<!-- html Document-->
<input type="button" value="点我有惊喜" onclick="alert('hello world')"/>

2.在js代码中进行事件绑定如 btn.onclick = function(){alert(“hello world”)}:

<!-- html Document-->
<input type="button" id="btn" value="点我有惊喜"/>
// javascript
var btn = document.getElementById("btn");
btn.onclick = function(){
	alert("hello world");
}

3.在 <script>标签通过 for 属性对对象进行事件绑定( IE only )

<!-- html Document-->
<input type="button" id="btn" value="点我有惊喜"/>
<script for = "btn" event = "onclick">(function a(){ alert("hello world!")})();</script>

4.添加事件 attachEvent( IE only )

语法:

obj.attachEvent(type,func)

  • obj:需要添加事件的对象
  • type:触发事件的类型 如 onclick
  • func:事件触发所调用的函数
<!-- html Document-->
<input type="button" id="btn" value="点我有惊喜"/>
// javascript
var btn = document.getElementById("btn");
btn.attachEvent("onclick",function(){
	alert("hello world");
});
	
}

5.添加事件监听器 addEventListener( IE9、firefox、opera 和其他webkit内核浏览器均支持 )

语法:

obj.addEventListener(type,func,bool)

  • obj:需要添加事件监听的对象
  • type:触发事件的类型 如 click
  • func:事件触发所调用的函数
  • bool:是否触发事件冒泡
<!-- html Document-->
<input type="button" id="btn" value="点我有惊喜"/>
// javascript
var btn = document.getElementById("btn");
btn.addEventListener("click",function(){
	alert("hello world");
},false);
	
}

事件解除

让事件解除绑定的方法有3种:

1.直接让触发函数为null:

// javascript
var btn = document.getElementById("btn");
btn.onclick = null;

这样做是最easy地对触发事件进行解绑定,但是问题是如果你绑定多个事件而你只想解除其中的一个事件的话,那这方法就不给力了。

2.删除事件 detachEvent:( ie only )

是和 attachEvent 一同使用,可以对已绑定的事件进行解绑定。

语法:

obj.detachEvent(type,func)

  • obj:需要解除事件绑定的对象
  • type:触发事件的类型 如 onclick
  • func:事件绑定时所调用的函数
// javascript
var btn = document.getElementById("btn");
function hello(){
	alert("hello world");
}

btn.attachEvent("onclick",hello);
btn.detachEvent("onclick",hello);

值得注意的是,这种解除绑定的方法,不支持匿名函数解绑定如:

// javascript
btn.attachEvent("onclick",function(){
	alert("hello world");
});

像这种方法是不能对这个事件进行 detachEvent 的。

3.移除事件监听器 removeEventListener( IE9、firefox、opera 和其他webkit内核浏览器均支持 )

与添加事件监听器 addEventListener 对应的,移除事件监听器 removeEventListener。

语法:

obj.removeEventListener(type,func,bool)

  • obj:需要移除事件监听的对象
  • type:触发事件的类型 如 click
  • func:事件触发所调用的函数
  • bool:是否触发事件冒泡
// javascript
var btn = document.getElementById("btn");

function hello(){
	alert("hello world");
}

btn.addEventListener("click",hello,false);
btn.removeEventListener("click",hello,false);

与 dettachEvent 方法类似,这种解除绑定的方法,不支持匿名函数解绑定。

关于事件的绑定和解除的几种方法已经介绍完了,下面,说说实际应用。

兼容全浏览器的事件添加与解除方法

添加事件与解除事件,由于低版本的 ie ( ie9 以下) 不支持添加事件监听 addEventListener,他们有自己的一套方法 attachEvent,所以想做到兼容全浏览器,就要将2者结合起来。

  • attachEvent 和 dettachEvent (ie only)
  • addEventListener 和 removeEventListener ( IE9、firefox、opera 和其他webkit内核浏览器均支持 )

实验原理:

判断当前浏览器是否支持调用的方法,各施各法。

代码:

//javascript
function addEvent(type,elm,func){
	if( elm.attachEvent ){
		elm.attachEvent("on" + type,func);
	}
	else if( elm.addEventListener){
		elm.addEventListener(type,func,false);
	}
}

function removeEvent(type,elm,func){
	if(elm.detachEvent){
		elm.detachEvent("on" + type,func)
	}
	else if(elm.removeEventListener){
		elm.removeEventListener(type,func,false)
	}
	
}

演示地址:http://www.jackness.org/lab/addevent/addevent_demo01.html

this的去向

通过处理和整合attaceEvent 和 addEventListener 后,可达到全浏览器兼容,在这里,通过这2种方法添加的 function,其中的 this 指向是否一致呢,因为这个疑问,所以有了以下的测试:

//javascript
function a(){ 
	alert(this);
}

addEvent("click",btn0,a);

结果如下图:

我们发现,通过 attachEvent添加的方法,this 是指向 window 的,而通过addEventListener 来添加的方法,this 是指向被添加方法的对象。

如何才能使 这2种添加事件的方法 中的 this 统一指向被添加方法对象呢?没错,可以通过 call 对 attachEvent 单独处理来实现:

//javascript
function addEvent(type,elm,func){
	if( elm.attachEvent ){
		elm.attachEvent("on" + type,function(){
			func.call(elm);
		});
	}
	else if( elm.addEventListener){
		elm.addEventListener(type,func,false);
	}
}

很遗憾地,运用这个方法之后又衍生出新的问题了

对匿名函数进行移除/删除

我们知道,attachEvent 和 addEventListener 都有一个比较弊的弊端,就是无法去除匿名函数:

//attachEvent
elm.attachEvent("onclick",function(){
	alert("hello world");
});

//addEventListener
elm.addEventListener("click",function(){
	alert("hello world");
},false)

以上这种添加方式中的 匿名函数是 无法通过 detachEvent/removeEventListener 来进行移除的。

为了解决这个问题,我在这里通过闭包来解决。下面是支持匿名函数的 添加删除事件 方法,不过调用方法稍微有点不一样:

function addEvent(type,elm,func){
	if(!elm){return;}
	if(elm.attachEvent){
		elm.attachEvent("on" + type,_attachEvent);
		return _attachEvent;
	}
	else if(elm.addEventListener){
		elm.addEventListener(type,_addEventListener,false);
		return _addEventListener;
	}
	
	function _attachEvent(){
		func.call(elm);
	}
	
	function _addEventListener(){
		func();
	}
}

function removeEvent(type,elm,func){
	if(!elm){return;}
	if(elm.detachEvent){
		elm.detachEvent("on" + type,func);
	}
	else if(elm.removeEventListener){
		elm.removeEventListener(type,func,false);
	}
}

使用方法:

var key;
key = addEvent("click",miku,function(){
	alert("爸爸~");
});	

removeEvent("click",miku,key);

演示地址:http://www.jackness.org/lab/addevent/addevent_demo02.html

然后我们会思考到一个问题:队列问题,经测试我们得知如果点了 添加按钮2次以上的话,删除按钮其实永远都只能删除最后一次添加的那个事件,其余的是删除不了的。

添加删除事件的队列问题

解决这个问题其实也很简单,我们可以将上面方法中的key由一个值变成一个数组,这样就可以解决这个问题了,在这里,由于貌似篇幅有点儿长了就不加述说了。

分类javascript
阅读 1,629
  • 评论加载中...

标签云

分类目录

最新留言

  • 评论加载中...

与我联系

如有疑问or建议可通过以下方式跟我取得联系.

Q Q:373435871
Email:jackness1208@gmail.com
© Copyright 2011 - 2014 jackNEss.org All Rights Reserved 粤ICP备14065612号
首页 | 关于我 | 网站地图 | RSS