• zepto 事件分析4(事件队列)


    前面分析了zepto的事件绑定,接下来分析事件解绑,先看一下zepto中解绑的off方法:

    $.fn.off = function(event, selector, callback){
        var $this = this
        if (event && !isString(event)) {
          $.each(event, function(type, fn){
            $this.off(type, selector, fn)
          })
          return $this
        }
    
        if (!isString(selector) && !isFunction(callback) && callback !== false)
          callback = selector, selector = undefined
    
        if (callback === false) callback = returnFalse
    
        return $this.each(function(){
          remove(this, event, callback, selector)
        })
      }

    offf方法前面大致和on方法一样,最主要的是最后return里面的remove函数,在看remove之前,要先分析之前遇到的有关handler的函数,下面是在add方法中,关于handler的。

    function add(element, events, fn, data, selector, delegator, capture){
        var id = zid(element), set = (handlers[id] || (handlers[id] = []))
        events.split(/s/).forEach(function(event){
         ...
          var handler   = parse(event)
          handler.fn    = fn
          handler.sel   = selector
          console.log(handler.e)
          // emulate mouseenter, mouseleave
          if (handler.e in hover) fn = function(e){
          ...
          }
          handler.del   = delegator
          var callback  = delegator || fn
          handler.proxy = function(e){
           ...
           ...
          }
          handler.i = set.length
          set.push(handler)
          if ('addEventListener' in element)
            element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
        })
      }

    首先通过zid函数设置一个id,并获得hanlders[id]数组,这里面使用了闭包的功能,在整个事件函数中定义了handlers和_zid两个变量,并在内部函数中采用函数的方式返回,使其不被回收。每个元素都有一个id,该id可以在handlers里面找到自己的事件队列。

    var _zid = 1,handlers = {};
    function zid(element) {
        return element._zid || (element._zid = _zid++)
     };
    function add(...){
    var id = zid(element), set = (handlers[id] || (handlers[id] = []));
    ...
    };
    $(".out").on('click',function(event) {
      console.log($(this))
      event.stopPropagation();
    });
    $(".in").on('click',function(event) {
      console.log($(this))
    });

    接下来,add函数定义了一个handler变量。该变量通过将event作为参数传入parse函数获得。

    function parse(event) {
        var parts = ('' + event).split('.')
        //返回一个对象,e为事件的type属性,ns为事件的命名空间
        return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
      }

    接下来,将事件的一系列相关参数放入handler里面,最后设置handler.i为set的长度(作为handler事件的一个index),并将handler放进set,也就是放进handlers[id]。

    也就是说,像上面的例子定义之后,handlers里面是这样的(每一个属性代表一个元素里面的事件队列,如1是对应的数组是div.in的事件队列)。

    分析handlers相关之后,就可以看remove函数了:

    function remove(element, events, fn, selector, capture){
       //获得元素在handlers中的对应id
        var id = zid(element)
        //遍历定义的事件
        ;(events || '').split(/s/).forEach(function(event){
          findHandlers(element, event, fn, selector).forEach(function(handler){
            delete handlers[id][handler.i]
          if ('removeEventListener' in element)
            element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
          })
        })
      }


    function findHandlers(element, event, fn, selector) {
        event = parse(event)
        if (event.ns) var matcher = matcherFor(event.ns)
        return (handlers[zid(element)] || []).filter(function(handler) {
          return handler
          && (!event.e || handler.e == event.e)
          && (!event.ns || matcher.test(handler.ns))
          && (!fn || zid(handler.fn) === zid(fn))
          && (!selector || handler.sel == selector)
        })
    }

     

    首先通过finHandlers函数来查询符合的事件,该函数相对简单,通过filter来返回一个符合条件的事件数组,接下来通过delete语句删除handlers[id]中对应的handler,并使用原生的解绑事件解绑。

    那么整个事件队列的分析就结束了,之前在分析$.on函数时,也有一个remove没有分析。

    $.fn.on = function(event, selector, data, callback, one){
        ...
        return $this.each(function(_, element){
          if (one) autoRemove = function(e){
            remove(element, e.type, callback)
            return callback.apply(this, arguments)
          }
          ...
          add(element, event, callback, data, selector, delegator || autoRemove)
        })
      }

    如果传入了one参数,那么就定义一个autoRemove函数,内部调用remove解绑,并返回绑定事件的执行。这样就保证了只执行一次。

  • 相关阅读:
    Android框架之路——OkGo的使用
    recyclerview23+出现多个item只显示第一个item的问题
    Spark MLlib回归算法LinearRegression
    Spark MLlib聚类KMeans
    Impala性能优化
    Impala通过JDBC方式访问
    Impala与HBase整合
    Impala数据处理(加载和存储)
    Impala SQL
    Impala储存与分区
  • 原文地址:https://www.cnblogs.com/Darlietoothpaste/p/6616177.html
Copyright © 2020-2023  润新知