Javascript添加监听与删除监听用法详解
本文实例讲述了Javascript添加监听与删除监听的用法。分享给大家供大家参考。具体分析如下:
js中事件监听就是利用addEventListener来绑定一个事件,这个用法在jquery中非常常用并且简单,但在原生js中比较复杂,这里整理了addEventListener事件各方法的测试与例子供大家参考学习。
在前两天做播放器的时候添加监听后删除监听遇到了一点麻烦,删不掉,后来看了一下才发现,参数需要完全对应,什么叫完全对应呢,换句话说:
$('.video')[0].addEventListener('timeupdate',currentTimeHandler,true);比如这句,需要传入三个参数,这样才能够删除,为什么一定要这样,没错,蛋疼的地方就在这里:
在add和remove时,第三个参数确实可以不写,但此时他们的默认情况是不一样的!!
通常情况下addEventListener是false…
1、添加自定义事件监听
vareventHandlesCounter=1;//统计添加事件监听的个数,0作为预留位
functionaddEvent(obj,evt,fn){
if(!fn.__EventID){fn.__EventID=eventHandlesCounter++;}
if(!obj.__EventHandles){obj.__EventHandles=[];}
if(!obj.__EventHandles[evt]){
obj.__EventHandles[evt]=[];
if(obj["on"+evt]instanceofFunction){
obj.__EventHandles[evt][0]=obj["on"+evt];
obj["on"+evt]=handleEvents;
}
}
obj.__EventHandles[evt][fn.__EventID]=fn;
functionhandleEvents(){
varfns=obj.__EventHandles[evt];
for(vari=0;i<fns.length;i++)
fns[i].call(this);
}
}2、自定义删除事件监听
functiondelEvent(obj,evt,fn){
if(!obj.__EventHandles||!obj.__EventHandles[evt]||!fn.__EventID){
returnfalse;
}
if(obj.__EventHandles[evt][fn.__EventID]==fn){
deleteobj.__EventHandles[evt][fn.__EventID];
}
}3.对上述方法进行修正
functionaddEvent(obj,evt,fn,useCapture){
if(obj.addEventListener){//优先使用W3C事件注册
obj.addEventListener(evt,fn,!!useCapture);
}else{
if(!fn.__EventID){fn.__EventID=addEvent.__EventHandlesCounter++;}
if(!obj.__EventHandles){obj.__EventHandles=[];}
if(!obj.__EventHandles[evt]){
obj.__EventHandles[evt]=[];
if(obj["on"+evt]){
(obj.__EventHandles[evtype][0]=obj["on"+evtype]).__EventID=0;
}
obj["on"+evtype]=addEvent.execEventHandles;
}
}
}
addEvent.__EventHandlesCounter=1;
addEvent.execEventHandles=function(evt){
if(!this.__EventHandles){returntrue;}
evt=evt||window.event;
varfns=this.__EventHandles[evt.type];
for(vari=0;i<fns.length;i++){
if(fns[i]instanceofFunction){
fns[i].call(this);
}
}
};
functiondelEvent(obj,evt,fn,useCapture){
if(obj.removeEventListener){//先使用W3C的方法移除事件处理函数
obj.removeEventListener(evt,fn,!!useCapture);
}else{
if(obj.__EventHandles){
varfns=obj.__EventHandles[evt];
if(fns){deletefns[fn.__EventID];}
}
}4、标准化事件对象
functionfixEvent(evt){
if(!evt.target){
evt.target=evt.srcElement;
evt.preventDefault=fixEvent.preventDefault;
evt.stopPropagation=fixEvent.stopPropagation;
if(evt.type=="mouseover"){
evt.relatedTarget=evt.fromElement;
}elseif(evt.type=="mouseout"){
evt.relatedTarget=evt.toElement;
}
evt.charCode=(evt.type=="keypress")?evt.keyCode:0;
evt.eventPhase=2;
evt.timeStamp=(newDate()).getTime();
}
returnevt;
}
fixEvent.preventDefault=function(){this.returnValue=false;}
fixEvent.stopPropagation=function(){this.cancelBubble=true;};
fixEvent函数不是单独执行的,它必须有一个事件对象参数,而且只有事件发生时它才被执行!最好的方法是把它整合到addEvent函数的execEventHandles里面。
addEvent.execEventHandles=function(evt){//遍历所有的事件处理函数并执行
if(!this.__EventHandles){returntrue;}
evt=fixEvent(evt||window.event);//在这里对其进行标准化操作
varfns=this.__EventHandles[evt.type];
for(vari=0;i<fns.length;i++){
if(fns[i]instanceofFunction){
fns[i].call(this,evt);//并且将其作为事件处理函数的第一个参数
//这样在事件处理函数内部就可以使用统一的方法访问事件对象了}}};
上面是高手写了,下面整理几个实际的监听事情的例子
<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
<html>
<head>
<title>test6.html</title>
<scripttype="text/javascript">
functiontest(){
window.alert("您投了一次票");
document.getElementById("1").detachEvent("onclick",test);
}
</script>
</head>
<body>
<inputtype="button"value="投票"id="1"/>
<scripttype="text/javascript">
document.getElementById("1").attachEvent("onclick",test);
</script>
</body>
</html>这里使用document.getElementById("1").attachEvent("onclick",test);进行动态的事件绑定,使用
document.getElementById("1").detachEvent("onclick",test)进行动态的时间的取消,这样就实现了这个事件只能相应一次,下次再点击这个按钮的时候就不会再产生什么效果。下面再演示一个时时监听键盘事件,判断输入的是否是数字,如果不是数字直接动态提示,然后拒绝其输入
<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
<html>
<head>
<title>test7.html</title>
<scripttype="text/javascript">
functiontest(event){
//用户每按下一个按键,就去判断是不是数字
if(event.keyCode<48||event.keyCode>57){
window.alert("您输入的不是一个数字");
returnfalse;
}
}
</script>
</head>
<body>
<inputtype="text"onkeypress="returntest(event);"/>请输入数字
</body>
</html>这里的event就是一个事件对象,他能返回很多的信息,具体请参考相关文档。
补充:事件监听方面的兼容
1.IE使用attachEvent/detachEvent方法来添加和删除事件监听器;w3c使用addEventListener/removeEventListener方法。
2.IE对其事件使用onevent的命名方式,而w3c的是event的命名方式。
3.IE事件监听器内使用的是一个全局的Event对象,而w3c是将event对象作为参数传递给监听器。
4.为了避免触发默认的事件行为,IE的做法是要求程序员设置Event对象中的returnValue属性值为false,而w3c的做法是执行preventDefault方法。
5.IE没有提供对事件捕获阶段的支持。
6.要停止事件的传递,IE的做法是设置event对象的cancelBubble为true,而w3c的做法是设置执行stopPropagation方法。
7.IE将事件监听器当做一个独立的函数来调用,而w3c中它是作为对象的方法来调用的,这表示在ie中事件监听器中的this关键字指向的不是事件发生对象而是一个没用的全局对象(window对象)。
8.IE在使用事件监听器方面存在内存泄露问题。在IE浏览器中,如果要为某个元素创建一个事件监听器,并且在监听器中使用该元素,则在用户进入其他页面之前,该监听器以及相关的DOM节点作占据的内存空间不会被释放。
希望本文所述对大家的javascript程序设计有所帮助。