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 相关文章推荐
filemanage功能中用到的lib.js
Apr 08 Javascript
jquery 学习之二 属性(类)
Nov 25 Javascript
不同编码的页面表单数据乱码问题解决方法
Feb 15 Javascript
使用AngularJS创建自定义的过滤器的方法
Jun 18 Javascript
JS+CSS实现鼠标滑过时动态翻滚的导航条效果
Sep 24 Javascript
Jquery Easyui进度条组件Progress使用详解(8)
Mar 26 Javascript
深入理解Vue.js源码之事件机制
Sep 27 Javascript
Vue中使用vee-validate表单验证的方法
May 09 Javascript
微信小程序中显示倒计时代码实例
May 09 Javascript
JavaScript简易计算器制作
Jan 17 Javascript
Vue之封装公用变量以及实现方式
Jul 31 Javascript
微信小程序学习之自定义滚动弹窗
Dec 20 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
PHPMailer邮件类利用smtp.163.com发送邮件方法
2008/09/11 PHP
yii用户注册表单验证实例
2015/12/26 PHP
Yii2使用$this-&gt;context获取当前的Module、Controller(控制器)、Action等
2017/03/29 PHP
PHP+jQuery实现即点即改功能示例
2019/02/21 PHP
JS获取dom 对象 ajax操作 读写cookie函数
2009/11/18 Javascript
JavaScript DOM学习第六章 表单实例
2010/02/19 Javascript
js或jquery实现页面打印可局部打印
2014/03/27 Javascript
javascript简单比较日期大小的方法
2016/01/05 Javascript
js 判断一组日期是否是连续的简单实例
2016/07/11 Javascript
ES2015 Symbol 一种绝不重复的值
2016/12/25 Javascript
jQuery与js实现颜色渐变的方法
2016/12/30 Javascript
实现jquery放大镜的两种方法
2018/02/22 jQuery
在vue项目中集成graphql(vue-ApolloClient)
2018/09/08 Javascript
Vue通过ref父子组件拿值方法
2018/09/12 Javascript
javascript实现滚动条效果
2020/03/24 Javascript
React实现评论的添加和删除
2020/10/20 Javascript
wxpython学习笔记(推荐查看)
2014/06/09 Python
python调用java模块SmartXLS和jpype修改excel文件的方法
2015/04/28 Python
python的构建工具setup.py的方法使用示例
2017/10/23 Python
python交互式图形编程实例(三)
2017/11/17 Python
Django使用httpresponse返回用户头像实例代码
2018/01/26 Python
对python特殊函数 __call__()的使用详解
2019/07/02 Python
Python基础之列表常见操作经典实例详解
2020/02/26 Python
Matlab中plot基本用法的具体使用
2020/07/17 Python
PyChon中关于Jekins的详细安装(推荐)
2020/12/28 Python
selenium携带cookies模拟登陆CSDN的实现
2021/01/19 Python
施华洛世奇美国官网:SWAROVSKI美国
2018/02/08 全球购物
中西医结合临床医学专业大学生自荐信
2013/09/28 职场文书
机电专业毕业生推荐信
2013/11/10 职场文书
大专毕业生自我评价分享
2013/11/10 职场文书
教师个人的自我评价分享
2014/01/02 职场文书
2014年教师个人工作总结
2014/11/10 职场文书
2015年前台文员工作总结
2015/05/18 职场文书
Java中PriorityQueue实现最小堆和最大堆的用法
2021/06/27 Java/Android
Spring Boot项目如何优雅实现Excel导入与导出功能
2022/06/10 Java/Android
阿里面试Nacos配置中心交互模型是push还是pull原理解析
2022/07/23 Java/Android