• 转:JavaScript中绑定事件监听函数的通用方法


    事件绑定的3中常用方法:传统绑定、W3C绑定方法、IE绑定方法。但是,在实际开发中对于我们来讲重要的是需要一个通用的、跨浏览器的绑定方法。如果我们在互联网上搜索一下会发现许多方法,一下是比较知名的几种方法:

    在开始学期下面几种方法之前,应当讨论一下,一个好的addEvent()方法应当达到哪些要求:

      a、支持同一元素的同一事件句柄可以绑定多个监听函数;

      b、如果在同一元素的同一事件句柄上多次注册同一函数,那么第一次注册后的所有注册都被忽略;

      c、函数体内的this指向的应当是正在处理事件的节点(如当前正在运行事件句柄的节点);

      d、监听函数的执行顺序应当是按照绑定的顺序执行;

      e、在函数体内不用使用 event = event || window.event; 来标准化Event对象;

    一、John Resig 所写的 addEvent() 函数:http://ejohn.org/projects/flexible-javascript-events/

    function addEvent( obj, type, fn ) {
            if ( obj.attachEvent ) {
                obj['e'+type+fn] = fn;
                obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
                obj.attachEvent( 'on'+type, obj[type+fn] );
            } else
                obj.addEventListener( type, fn, false );
        }
        function removeEvent( obj, type, fn ) {
            if ( obj.detachEvent ) {
                obj.detachEvent( 'on'+type, obj[type+fn] );
                obj[type+fn] = null;
            } else
                obj.removeEventListener( type, fn, false );
        }

    这个函数如此简单易懂,的确非常令人惊讶。那么我们还是要看看上面的五点要求:

      对于第一点满足了;

      对于第三点和第五点,肯定也满足了;

      对于第二点,并没有满足,因为addEventListener()会忽略重复注册,而attachEvent()则不会忽略;

      但是第四点,并没有满足,因为Dom标准没有确定调用一个对象的时间处理函数的顺序,所以不应该想当然的认为它们以注册的顺序调用。

    但是这个函数仍然是一个非常优秀的函数。

    ppk在《ppk谈javascript》里面推荐的两个函数:

    function addEventSimple(obj,evt,fn) {
     if (obj.addEventListener)
      obj.addEventListener(evt,fn,false);
     else if (obj.attachEvent)
      obj.attachEvent('on'+evt,fn);
    }
    
    function removeEventSimple(obj,evt,fn) {
     if (obj.removeEventListener)
      obj.removeEventListener(evt,fn,false);
     else if (obj.detachEvent)
      obj.detachEvent('on'+evt,fn);
    }

    个函数解决了给一个元素绑定多个事件处理函数的问题,然而缺点是在ie里面是事件处理函数里面的this关键字不能指向所绑定的DOM对象,而是指向window对象,即作用域错误

     

    Dean Edwards也写了一个自己的addEvent()函数

    // written by Dean Edwards, 2005
    // http://dean.edwards.name/
    
    function addEvent(element, type, handler) {
      // 为每个事件处理程序分配一个唯一的id
      if (!handler.$$guid) handler.$$guid = addEvent.guid++;
      // 为该元素的各种事件类型创建一个hash表
      if (!element.events) element.events = {};
      // 为每一个元素/事件对的所有事件处理程序创建一个hash表
      var handlers = element.events[type];
      if (!handlers) {
        handlers = element.events[type] = {};
        // 存储已经存在的事件处理程序(如果有的话)
        if (element["on" + type]) {
          handlers[0] = element["on" + type];
        }
      }
      // 将事件处理程序存储到hash表内
      handlers[handler.$$guid] = handler;
      // 剩下的任务交给一个全局的事件处理程序来搞定
      element["on" + type] = handleEvent;
    };
    // 一个用来分配唯一ID的计数器
    addEvent.guid = 1;
    
    function removeEvent(element, type, handler) {
      // 从hash表里面删除该事件处理程序
      if (element.events && element.events[type]) {
        delete element.events[type][handler.$$guid];
      }
    };
    function handleEvent(event) {
      var returnValue = true;
      // 取得event对象(IE使用了一个全局的事件对象)
      event = event || fixEvent(window.event);
      // 找到事件处理程序的hash表
      var handlers = this.events[event.type];
      // 执行各个事件处理程序
      for (var i in handlers) {
        this.$$handleEvent = handlers[i];
        if (this.$$handleEvent(event) === false) {
          returnValue = false;
        }
      }
      return returnValue;
    };
    
    function fixEvent(event) {
      // 增加符合W3C标准的事件模型
      event.preventDefault = fixEvent.preventDefault;
      event.stopPropagation = fixEvent.stopPropagation;
      return event;
    };
    fixEvent.preventDefault = function() {
      this.returnValue = false;
    };
    fixEvent.stopPropagation = function() {
      this.cancelBubble = true;
    };

    Dean Edwards的这个方法是相对来说最完美的一个方案,没有使用addEventListener和attachEvent就实现了多重函数的绑定,并且事件处理函数支持this关键字。

    上面提到的这些都有提供相配套的解除绑定函数,但是大部分时候我们只需要绑定,不需要解绑,这种情况下下面这个简单的函数已经足够满足我们的需要了。

    function addEvent( obj, type, fn ){
           
    if(obj.addEventListener)
                    obj
    .addEventListener(type, fn,false);
           
    elseif(obj.attachEvent)
                    obj
    .attachEvent('on'+ type,function(){return fn.call(obj, window.event);});
    }

    大部分开源的js框架,如jQuery和YUI都有提供很方便的事件绑定接口,其实现的方式就复杂多了,当然功能也要强大得多。

    来自:http://biaoge.me/2009/12/253

     

  • 相关阅读:
    题解 SP27102/UVA1747 【Swap Space】
    题解 P1453 【城市环路】
    题解 P5587 【打字练习】
    题解 P5594 【【XR-4】模拟赛】
    git add 的一点说明
    理解 Git 的基本概念 ( Merging Collaborating Rebasing)
    windows 上 Python 通过 SCP 连接linux server
    Neo4j CQL | WITH用法
    Neo4j CQL |create &merge
    Item 4: Prefer Interpolated F-Strings Over C-style Format Strings and str.format(请使用f-string格式化字符串)
  • 原文地址:https://www.cnblogs.com/youxin/p/2659444.html
Copyright © 2020-2023  润新知