前面分析了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解绑,并返回绑定事件的执行。这样就保证了只执行一次。

zepto 事件分析4(事件队列)的更多相关文章

  1. zepto 事件分析2($.on)

    这里主要分析zepto事件中的$.on函数,先看一下该函数的代码 $.fn.on = function(event, selector, data, callback, one){ var autoR ...

  2. zepto 事件分析1($.Event)

    先看一下zepto事件的函数,在这里,zepto是把zepto对象作为一个立即执行函数的参数传进去的. (function($){ ... ... })(Zepto) 在zepto事件函数中,主要为$ ...

  3. zepto 事件分析3(add函数)

    在上一篇的分析中,最后$.on方法返回了一个add方法函数的执行,在这里先看一下其代码: function add(element, events, fn, data, selector, deleg ...

  4. Zepto事件模块源码分析

    Zepto事件模块源码分析 一.保存事件数据的handlers 我们知道js原生api中要移除事件,需要传入绑定时的回调函数.而Zepto则可以不传入回调函数,直接移除对应类型的所有事件.原因就在于Z ...

  5. 移动web app开发必备 - zepto事件问题

    问题描述: 项目在祖先元素上绑定了 touchstart,touchmove,touchend事件,用来处理全局性的事件,比如滑动翻页 正常状态下: 用户在子元素上有交互动作时,默认状态下都是会冒泡到 ...

  6. OneAlert 入门(三)——事件分析

    OneAlert 是国内首个 SaaS 模式的云告警平台,集成国内外主流监控/支撑系统,实现一个平台上集中处理所有 IT 事件,提升 IT 可靠性.有了 OneAlert,你可以更快更合理地为事件划分 ...

  7. OneAlert 入门(二)——事件分析

    OneAlert 是国内首个 SaaS 模式的云告警平台,集成国内外主流监控/支撑系统,实现一个平台上集中处理所有 IT 事件,提升 IT 可靠性.有了 OneAlert,你可以更快更合理地为事件划分 ...

  8. 跨浏览器resize事件分析

    resize事件 原生事件分析 window一次resize事件: IE7 触发3次, IE8 触发2次, IE9 触发1次, IE10 触发1次 Chrome 触发1次 FF 触发2次 Opera ...

  9. GridView事件分析

    GridView事件分析 (转) P1默认数据绑定过程 编号 事件名称 作用 E1 DataBinding 数据绑定之前触发,在这个事件之前(第一次生成GridView),GridView不存在行数据 ...

随机推荐

  1. socket的阻塞与非阻塞,同步与非同步

    网络编程中通常提到四种方式,同步/异步,阻塞/非阻塞.以下对它们的概念进行总结 1.同步/异步:主要针对C端 同步:所谓同步,就是在C端发出一个功能调用时,在没有得到结果之前,调用不返回,也就是必须一 ...

  2. Debian 8.x / Ubuntu 16.04.x 搭建 Ghost 教程

    Ghost 是一款使用 Node.js 开发的博客系统,相对于使用 PHP 开发的 WordPress 更轻巧友好,所以本站已经从 WordPress 切换至 Ghost,本文介绍在 Debian 8 ...

  3. jdk环境变量的设置

    一.jdk下载网址 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 二.环境变 ...

  4. pyqt5安装问题

    最近装了下pyqt5,遇到了很多坑,要么是模块没找到,要么是各种ddl出错什么的 后来查了一下,总结一下: 1.pyqt5和python的版本一定匹配,尤其是自己去网上下的pyqt一定要注意适配的版本 ...

  5. 《Java性能调优》学习笔记(1)

    性能的参考指标 执行时间 -- 从代码开始运行到结束的时间 CPU时间 -- 函数或者线程占用CPU的时间 内存分配 -- 程序在运行时占用内存的情况 磁盘吞吐量 -- 描述IO的使用情况 网络吞吐量 ...

  6. 大叔学ML第一:梯度下降

    目录 原理 实践一:求\(y = x^2 - 4x + 1\)的最小值 实践二:求\(z = x^2 + y^2 + 5\)的最小值 问答时间 原理 梯度下降是一个很常见的通过迭代求解函数极值的方法, ...

  7. 转载:Package by feature, not layer

    原文地址:Package by feature, not layer Package by feature, not layer The first question in building an a ...

  8. jquery mobile Touch事件

    Touch事件在用户触摸屏幕(页面)时触发 1.jquery mobile tap tap事件在用户敲击某个元素时触发 $("p").on("tap",fucn ...

  9. Spark机器学习(上)

    1.机器学习概念 1.1 机器学习的定义 在维基百科上对机器学习提出以下几种定义: l“机器学习是一门人工智能的科学,该领域的主要研究对象是人工智能,特别是如何在经验学习中改善具体算法的性能”. l“ ...

  10. Spring依赖注入(DI)详解

    一.依赖简介 一个典型的企业应用程序不是由一个单一的对象组成(或Spring的说法中的bean).即使是最简单的应用程序也只有几个对象一起工作来呈现最终用户看作是一个连贯的应用程序.如何从定义许多独立 ...