Javascript添加监听与删除监听用法详解


Posted in Javascript onDecember 19, 2014

本文实例讲述了Javascript添加监听与删除监听的用法。分享给大家供大家参考。具体分析如下:

js中事件监听就是利用addEventListener来绑定一个事件,这个用法在jquery中非常常用并且简单,但在原生js中比较复杂,这里整理了addEventListener事件各方法的测试与例子供大家参考学习。

在前两天做播放器的时候添加监听后删除监听遇到了一点麻烦,删不掉,后来看了一下才发现,参数需要完全对应,什么叫完全对应呢,换句话说:

$('.video')[0].addEventListener('timeupdate', currentTimeHandler, true);

比如这句,需要传入三个参数,这样才能够删除,为什么一定要这样,没错,蛋疼的地方就在这里:
在add和remove时,第三个参数确实可以不写,但此时他们的默认情况是不一样的!!

通常情况下addEventListener是false…
1、 添加自定义事件监听

var eventHandlesCounter=1;//统计添加事件监听的个数,0作为预留位

    function addEvent(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] instanceof Function){

              obj.__EventHandles[evt][0]=obj["on"+evt];

              obj["on"+evt]=handleEvents;

           }

       }

       obj.__EventHandles[evt][fn.__EventID]=fn;

 

       function handleEvents(){

         var fns = obj.__EventHandles[evt];

         for (var i=0;i<fns.length;i++)

            fns[i].call(this);

       }

}

2、自定义删除事件监听
function delEvent(obj,evt,fn){

   if(!obj.__EventHandles || !obj.__EventHandles[evt] || !fn.__EventID){

      return false;

   }

   if(obj.__EventHandles[evt][fn.__EventID]==fn){

      delete obj.__EventHandles[evt][fn.__EventID];

   }

}

3. 对上述方法进行修正
function addEvent(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) {return true;}

    evt = evt || window.event;

    var fns = this.__EventHandles[evt.type];

    for (var i=0;i<fns.length;i++){

       if(fns[i] instanceof Function){

           fns[i].call(this);

       }

    }

};

function delEvent(obj,evt,fn,useCapture){

   if (obj.removeEventListener) {//先使用W3C的方法移除事件处理函数         

       obj.removeEventListener(evt,fn,!!useCapture);

   }else {

      if(obj.__EventHandles){

         var fns = obj.__EventHandles[evt];

         if(fns){delete fns[fn.__EventID];}

      }

}

4、标准化事件对象
function fixEvent(evt){

   if(!evt.target){

      evt.target = evt.srcElement;

      evt.preventDefault=fixEvent.preventDefault;

      evt.stopPropagation = fixEvent.stopPropagation;

      if(evt.type == "mouseover"){

         evt.relatedTarget = evt.fromElement;

      }else if(evt.type == "mouseout"){

         evt.relatedTarget = evt.toElement;

      }

      evt.charCode =(evt.type == "keypress")?evt.keyCode:0;

      evt.eventPhase = 2;

      evt.timeStamp = (new Date()).getTime();

   }

return evt;

}

fixEvent.preventDefault=function(){ this.returnValue=false;}

fixEvent.stopPropagation=function(){this.cancelBubble = true;};

fixEvent函数不是单独执行的,它必须有一个事件对象参数,而且只有事件发生时它才被执行!最好的方法是把它整合到addEvent函数的execEventHandles里面。

addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行

if (!this.__EventHandles) {return true;}

evt = fixEvent(evt || window.event);//在这里对其进行标准化操作

var fns = this.__EventHandles[evt.type];

for (var i=0;i< fns.length;i++) {

if (fns[i] instanceof Function) {

fns[i].call(this,evt);//并且将其作为事件处理函数的第一个参数

//这样在事件处理函数内部就可以使用统一的方法访问事件对象了 } } };

上面是高手写了,下面整理几个实际的监听事情的例子

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>test6.html</title>

 <script type="text/javascript">

  function test(){

   window.alert("您投了一次票");

   document.getElementById("1").detachEvent("onclick",test);

  }

 </script>

  </head>

  

  <body>

    <input type="button" value="投票" id="1"/>

    <script type="text/javascript">

     document.getElementById("1").attachEvent("onclick",test);

    </script>

  </body>

</html>

这里使用document.getElementById("1").attachEvent("onclick",test);进行动态的事件绑定,使用
document.getElementById("1").detachEvent("onclick",test)
进行动态的时间的取消,这样就实现了这个事件只能相应一次,下次再点击这个按钮的时候就不会再产生什么效果。
下面再演示一个时时监听键盘事件,判断输入的是否是数字,如果不是数字直接动态提示,然后拒绝其输入
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>test7.html</title>

 <script type="text/javascript">

  function test(event){

   //用户每按下一个按键,就去判断是不是数字

   if(event.keyCode<48 || event.keyCode > 57){

    window.alert("您输入的不是一个数字");

    return false;

   }

  }

 </script>

  </head>

  

  <body>

    <input type="text" onkeypress="return test(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程序设计有所帮助。

Javascript 相关文章推荐
jQuery使用empty()方法删除元素及其所有子元素的方法
Mar 26 Javascript
Jquery实现弹性滑块滑动选择数值插件
Aug 08 Javascript
js限制文本框的输入内容代码分享(3类)
Aug 20 Javascript
原生javascript实现读写CSS样式的方法详解
Feb 20 Javascript
JavaScript中数组Array.sort()排序方法详解
Mar 01 Javascript
JavaScript基础之this详解
Jun 04 Javascript
浅谈使用React.setState需要注意的三点
Dec 18 Javascript
详解angular部署到iis出现404解决方案
Aug 14 Javascript
微信小程序实现两边小中间大的轮播效果的示例代码
Dec 07 Javascript
npm 常用命令详解(小结)
Jan 17 Javascript
vue生命周期与钩子函数简单示例
Mar 13 Javascript
ES6常用小技巧总结【去重、交换、合并、反转、迭代、计算等】
Dec 21 Javascript
Javascript 实现图片无缝滚动
Dec 19 #Javascript
使用JavaScript获取地址栏参数的方法
Dec 19 #Javascript
JS获取各种宽度、高度的简单介绍
Dec 19 #Javascript
JQuery右键菜单插件ContextMenu使用指南
Dec 19 #Javascript
简单谈谈jQuery(function(){})与(function(){})(jQuery)
Dec 19 #Javascript
jQuery多级弹出菜单插件ZoneMenu
Dec 18 #Javascript
使用jquery菜单插件HoverTree仿京东无限级菜单
Dec 18 #Javascript
You might like
php 正则匹配函数体
2009/08/25 PHP
php提示无法加载或mcrypt没有找到 PHP 扩展 mbstring解决办法
2012/03/27 PHP
两种php去除二维数组的重复项方法
2015/11/04 PHP
PHP如何根据文件头检测文件类型实例代码
2018/10/14 PHP
简单三步,搞掂内存泄漏
2007/03/10 Javascript
javascript限制文本框只允许输入数字(曾经与现在的方法对比)
2013/01/18 Javascript
JQUERY 实现窗口滚动搜索框停靠效果(类似滚动停靠)
2013/03/27 Javascript
js+csss实现的一个带复选框的下拉框
2014/09/29 Javascript
JS实现新浪博客左侧的Blog管理菜单效果代码
2015/10/22 Javascript
js实现仿qq消息的弹出窗效果
2016/01/06 Javascript
Angular2平滑升级到Angular4的步骤详解
2017/03/29 Javascript
基于JQuery和原生JavaScript实现网页定位导航特效
2017/04/03 jQuery
JS图片预加载插件详解
2017/06/21 Javascript
vue.js todolist实现代码
2017/10/29 Javascript
解决Vue.js由于延时显示了{{message}}引用界面的问题
2018/08/25 Javascript
详解如何给React-Router添加路由页面切换时的过渡动画
2019/04/25 Javascript
原生js生成图片验证码
2020/10/11 Javascript
[48:53]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS VG第一场
2014/05/26 DOTA
详解Python中break语句的用法
2015/05/14 Python
好用的Python编辑器WingIDE的使用经验总结
2016/08/31 Python
Python开发微信公众平台的方法详解【基于weixin-knife】
2017/07/08 Python
python在ubuntu中的几种安装方法(小结)
2017/12/08 Python
Python实现爬虫从网络上下载文档的实例代码
2018/06/13 Python
python实现flappy bird小游戏
2018/12/24 Python
Python内置方法和属性应用:反射和单例(推荐)
2020/06/19 Python
python 5个顶级异步框架推荐
2020/09/09 Python
python 实现表情识别
2020/11/21 Python
ECCO爱步官方旗舰店:丹麦鞋履品牌
2018/01/02 全球购物
打造完美自荐信
2014/01/24 职场文书
兰兰过桥教学反思
2014/02/08 职场文书
大学生职业生涯规划大赛作品(精品)
2014/09/17 职场文书
运动会400米加油稿(8篇)
2014/09/22 职场文书
2014年法务工作总结
2014/12/11 职场文书
读后感作文评语
2014/12/25 职场文书
python spilt()分隔字符串的实现示例
2021/05/21 Python
Win11怎么修改电源模式?Win11修改电源模式的方法
2022/04/05 数码科技