这里主要分析zepto事件中的$.on函数,先看一下该函数的代码

$.fn.on = function(event, selector, data, callback, one){
var autoRemove, delegator, $this = this
if (event && !isString(event)) {
//多个事件下的处理
$.each(event, function(type, fn){
$this.on(type, selector, data, fn, one)
})
return $this
}
//根据传入的参数初始化各个参数
//(event,data,callback)
if (!isString(selector) && !isFunction(callback) && callback !== false)
callback = data, data = selector, selector = undefined
//(event,selector,callback)
if (callback === undefined || data === false)
callback = data, data = undefined
//callback = function(){return false}
if (callback === false) callback = returnFalse
//迭代zepto对象中的元素
return $this.each(function(_, element){
if (one) autoRemove = function(e){
remove(element, e.type, callback)
return callback.apply(this, arguments)
}
//如果有传入选择器 定义一个delegator函数
if (selector) delegator = function(e){
//从触发事件目标出发找寻符合selector选择器的元素
var evt, match = $(e.target).closest(selector, element).get(0)
//如果存在并且不是element
if (match && match !== element) {
//对event对象进行转化操作
evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))
}
}
add(element, event, callback, data, selector, delegator || autoRemove)
})
}

该函数主要分析的是return 后面的语句,在前面的分析中,分析了each函数和$对象,也就是对$对象中的每一个dom进行绑定事件,这里先跳过autoRemove函数,留在后面分析,如果有传入选择器,zepto先定义一个delegator函数,delegator函数中有一个match变量,该变量即为我们要绑定事件的目标元素,zepto采用的是事件委托,官方文档对于closest的定义如下:

而e.target即是事件触发的元素,注意:currentTarget和e.target是不同的。target在事件流的目标阶段;currentTarget在事件流的捕获,目标及冒泡阶段。

<body>
<div class="out">
<div class="in"><h2>1`</h2></div>
</div>
</html>
<script type="text/javascript"> function test2(e){
console.log(e.target);
console.log(e.currentTarget)
};
var box2 = document.getElementsByClassName('in')[0];
box2.addEventListener("click",test2);

当我们点击h2时,target指向<h2>,currentTarget指向<div class='in'>;

在获得match之后,判断其是否存在或是否为元素本身,如果是,则什么都不做,如果不是,则创建一个新的事件evt,并将原来的事件属性赋值给evt,并改变currentTarget和 liveFired的属性值。

其中有一个createProxy函数,该函数的功能即为复制属性。

function createProxy(event) {
var key, proxy = { originalEvent: event }
for (key in event)
if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key] return compatible(proxy, event)
}

createProxy函数最后返回的是一个compatible函数的执行,在之前分析$.Event就有遇到过,在这里来分析其作用。

function compatible(event, source) {
//如果没有传入source函数并且evnet事件阻止了默认操作,则直接返回传入的event参数
if (source || !event.isDefaultPrevented) {
source || (source = event) $.each(eventMethods, function(name, predicate) {
var sourceMethod = source[name]
event[name] = function(){
this[predicate] = returnTrue
return sourceMethod && sourceMethod.apply(source, arguments)
}
event[predicate] = returnFalse
}) event.timeStamp || (event.timeStamp = Date.now())
//对其默认操作进行相关判断
if (source.defaultPrevented !== undefined ? source.defaultPrevented :
'returnValue' in source ? source.returnValue === false :
source.getPreventDefault && source.getPreventDefault())
event.isDefaultPrevented = returnTrue
}
return event
}

该函数最主要的代码在中间的$.each(...),可以先看一下eventMethods的定义

eventMethods = {
preventDefault: 'isDefaultPrevented',
stopImmediatePropagation: 'isImmediatePropagationStopped',
stopPropagation: 'isPropagationStopped'
}

在原生的事件属性中,也存在prereventDefault等方法以及判断其值的defaultPrevented属性,但在zepto中,每次绑定事件,实际上都相当于重新定义一个事件,而自我定义的属性是不具备prereventDefault等方法的功能,那么defaultPrevented的值也就失效了。如图:

function test2(e){
var evt = {};
for(key in evt)
evt[key] = e[key];
evt.preventDefault();
};
var box2 = document.getElementsByClassName('in')[0];
box2.addEventListener("click",test2);

所以compatible函数的作用就是为了使原生事件preventDefault等的方法以及判断其值的属性转变为一个方法来使用。

delegator函数中,最后返回的是对绑定函数的执行。

最后on方法执行了一个add()函数,该函数留在下一篇分析。

zepto 事件分析2($.on)的更多相关文章

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

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

  2. zepto 事件分析4(事件队列)

    前面分析了zepto的事件绑定,接下来分析事件解绑,先看一下zepto中解绑的off方法: $.fn.off = function(event, selector, callback){ var $t ...

  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. How Does Closure Work in Javascript?

    Simply, closure is the scope that it can visite and operate the variables outside of the function wh ...

  2. bzoj1031(sa)

    省选前练习模板系列: #include<iostream> #include<cstdio> #include<cmath> #include<cstring ...

  3. Nginx 教程(2):性能

    tcp_nodelay, tcp_nopush 和 sendfile tcp_nodelay 在 TCP 发展早期,工程师需要面对流量冲突和堵塞的问题,其中涌现了大批的解决方案,其中之一是由 John ...

  4. Android中监控USB的插拔

    一.需求 在Android应该开发过程中,用到了USB通讯,需要应用监控USB设备的插入和拔出,从而刷新USB设备列表. 二.实现 在使用时,需要register和unregister. 通过UsbD ...

  5. centos 7 默认图形界面(或者字符界面)启动

    1.切换到管理员用户 2.systemctl get-default命令获取当前模式(可以省去) 3.systemctl set-default graphical.target 修改启动模式(修改为 ...

  6. 关于Nginx设置端口号,在Asp.net 获取不到的,解决办法

    不知道你有没有遇到过这样的问题,网站访客多起来后,心里很是高兴,加上了Nginx反向代理,出问题了 原来是这么写的: Request.Url.ToString() 输出是这样的: http://www ...

  7. ES6之命令妙用

     很多人都听说过ES6(也就是ECMAScript的新一代标准)并且对她充满了向往,下面通过一个ES6中小知识点——let命令,来解开她的神秘面纱,让大家初步认识一下ES6的语法规范.        ...

  8. Android 代码混淆配置总结

    一.前言 为何需要混淆呢?简单的说,就是将原本正常的项目文件,对其类,方法,字段,重新命名,a,b,c,d,e,f…之类的字母,达到混淆代码的目的,这样反编译出来,结构乱糟糟的,看了也头大. 另外说明 ...

  9. Python学习笔记【第十四篇】:Python网络编程二黏包问题、socketserver、验证合法性

    TCP/IP网络通讯粘包问题 案例:模拟执行shell命令,服务器返回相应的类容.发送指令的客户端容错率暂无考虑,按照正确的指令发送即可. 服务端代码 # -*- coding: utf- -*- # ...

  10. Linux 总是提示You have new mail in /var/spool/mail/root

    解决办法: echo “unset MAILCHECK” >> /etc/profile source /etc/profile 这样就可以了!!!!!!!!!!