位置:海鸟网 > IT > JavaScript >

javascript 绑定切换

jQuery有关事件绑定的函数太丰富了,今天由于某需求,需要一种每次点击触发不同的回调函数的效果,因此瞄一瞄jQuery的API,发现toggle正是我要的,于是也给我框架添一个。但jQuery的实现太复杂了,闭包套嵌过多,我换另一种思路轻松实现了它。

下面是jQuery的实现:

//===============代理函数===============

        proxy: function( fn, proxy, thisObject ) {

            if ( arguments.length === 2 ) {

                if ( typeof proxy === "string" ) {

                    thisObject = fn;

                    fn = thisObject[ proxy ];

                    proxy = undefined;

  

                } else if ( proxy && !jQuery.isFunction( proxy ) ) {

                    thisObject = proxy;

                    proxy = undefined;

                }

            }

  

            if ( !proxy && fn ) {

                proxy = function() {

                    return fn.apply( thisObject || this, arguments );

                };

            }

  

            // Set the guid of unique handler to the same of original handler, so it can be removed

            if ( fn ) {

                proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;

            }

  

            // So proxy can be declared as an argument

            return proxy;

        },

//===============绑定切换函数===============

      toggle: function( fn ) {

        // Save reference to arguments for access in closure

        var args = arguments, i = 1;

  

        // link all the functions, so any of them can unbind this click handler

        while ( i < args.length ) {

          jQuery.proxy( fn, args[ i++ ] );

        }

  

        return this.click( jQuery.proxy( fn, function( event ) {

          // Figure out which function to execute

          var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;

          jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );

  

          // Make sure that clicks stop

          event.preventDefault();

  

          // and execute the function

          return args[ lastToggle ].apply( this, arguments ) || false;

        }));

      },

这是我的实现:

toggle:function(/*fn1,fn2,fn3*/){

    var callback = function(event){

        var self = arguments.callee;

        try{

            self["fn"+self._toggle].call(this,event)

        }catch(e){

            self._toggle =0 ;

            self["fn"+self._toggle].call(this,event)

        }

        self._toggle ++

    }

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

        callback["fn"+i] = arguments[i];

    }

    return this.click(callback)

}

由于我不可能把我的事件模块放出来,它与jQuery的事件模块一样精致与复杂,换言之,一样易碎,强行分割就动弹不了。不过结合我早期放出的addEvent函数,还是能做出来的,虽然事件队列与事件对象还没有现整化。

      var addEvent = function(el, type, fn) {

        if (el.addEventListener) {

          el.addEventListener(type, fn, false);//DOM2.0

        }else if (el.attachEvent) {

          el.attachEvent('on' + type, function(){

            fn.call(el,window.event)

          });

        }

      }

      var toggle = function(el/*,fn1,fn2,fn3*/){

        var callback = function(event){

          var self = arguments.callee;

          try{

            self["fn"+self._toggle].call(this,event)

          }catch(e){

            self._toggle =0 ;

            self["fn"+self._toggle].call(this,event)

          }

          self._toggle ++

        }

        var fns = [].slice.call(arguments,1);

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

          callback["fn"+i] = fns[i];

        }

        addEvent(el,"click",callback);

      }

//=========经群里高人指点,继续简化与优化=====

      var toggle2 = function(el) {

        var fns = [].slice.call(arguments, 1),

        backup = fns.concat();

        addEvent(el, 'click', function(e){

          if (!fns.length) { fns = backup.concat()}

          fns[0].call(this,e);

          fns.shift();

        });

      };

用法与例子:

运行代码