zepto 事件分析3(add函数)
在上一篇的分析中,最后$.on方法返回了一个add方法函数的执行,在这里先看一下其代码:
function add(element, events, fn, data, selector, delegator, capture){
var id = zid(element), set = (handlers[id] || (handlers[id] = []))
events.split(/\s/).forEach(function(event){
if (event == 'ready') return $(document).ready(fn)
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){
var related = e.relatedTarget
if (!related || (related !== this && !$.contains(this, related)))
return handler.fn.apply(this, arguments)
}
handler.del = delegator
var callback = delegator || fn
handler.proxy = function(e){
e = compatible(e)
if (e.isImmediatePropagationStopped()) return
e.data = data
var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))
if (result === false) e.preventDefault(), e.stopPropagation()
return result
}
handler.i = set.length
set.push(handler)
if ('addEventListener' in element)
element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
})
}
在这里先跳过id以及handler部分(handler.e的值即为事件的type属性),该函数主要作用就是将事件添加进元素的事件队列里。
首先是对events进行分割成多个事件,并通过each函数逐个绑定。先来看一下函数里面的条件判定:
hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }
if (handler.e in hover) fn = function(e){
var related = e.relatedTarget
if (!related || (related !== this && !$.contains(this, related)))
return handler.fn.apply(this, arguments)
}
如果事件的type属性是mouseenter或者mouseleave,那么需要重新定义绑定函数fn,什么是relatedTarget呢?
relatedTarget
属性用于在一个事件中查找另外一个元素。有些事件比如 mouseover
通常侧重处理一个特定的目标,而有些有也可能会涉及到第二目标,比如当目标退出第一目标的 mouseover
事件.
获得relatedTarget元素后,zepto对其进行判断,if (!related || (related !== this && !$.contains(this, related))),假设我们有两个div。
<div class="out">
<div class="in"></div>
</div>
我们对div.out定义mouseenter事件后,当我们鼠标从div.in移出来,但鼠标仍然在div.out,那么鼠标自始至终都在div.out中,但还是触发了mouseenter事件,这可能与预期中不同,所以zepto在这里加了判断,如果relatedTarget元素不存在,或者relatedTarget元素不是我们想要触发的元素本身,并且不包含在其中,即返回一个调用原来的fn函数。
接下来就是handler.proxy函数了,该函数的作用就是通过apply调用绑定的事件函数,并返回结果。
最后通过原生addEvent来绑定函数。
最后,总结一下zepto中绑定事件的思路:
1.找到目标元素。 即match = $(e.target).closest(selector, element).get(0),如果没有selector即跳过。
2.事件委托。如果存在selector,即重新生成一个事件,并通过compitable,createProxy对其进行修改,并改变其currentTarget属性,如果不存在selector,即对要绑定的dom执行compitable,添加eventMethod中的方法。
3.事件绑定,当存在selector触发时,实际触发的是$对象中的dom元素,只是通过事件委托使得像在符合selector条件元素中执行一样。
ps:当存在selector时,假设绑定了click事件,但点击的是$对象中的dom元素并且区域不在selector中,同样触发了事件对象,只是上一篇中的delegator函数里,如果找不到selector,那么跳过,不执行我们绑定的函数。$中的dom元素绑定的是handler.proxy函数,handler.proxy返回的是delegator的执行结果,而delegator如果找不到selector,那么就不执行我们绑定的函数。
zepto 事件分析3(add函数)的更多相关文章
- zepto 事件分析2($.on)
这里主要分析zepto事件中的$.on函数,先看一下该函数的代码 $.fn.on = function(event, selector, data, callback, one){ var autoR ...
- zepto 事件分析4(事件队列)
前面分析了zepto的事件绑定,接下来分析事件解绑,先看一下zepto中解绑的off方法: $.fn.off = function(event, selector, callback){ var $t ...
- zepto 事件分析1($.Event)
先看一下zepto事件的函数,在这里,zepto是把zepto对象作为一个立即执行函数的参数传进去的. (function($){ ... ... })(Zepto) 在zepto事件函数中,主要为$ ...
- Zepto事件模块源码分析
Zepto事件模块源码分析 一.保存事件数据的handlers 我们知道js原生api中要移除事件,需要传入绑定时的回调函数.而Zepto则可以不传入回调函数,直接移除对应类型的所有事件.原因就在于Z ...
- jQuery源码解读-事件分析
最原始的事件注册 addEventListener方法大家应该都很熟悉,它是Html元素注册事件最原始的方法.先看下addEventListener方法签名: element.addEventList ...
- 移动web app开发必备 - zepto事件问题
问题描述: 项目在祖先元素上绑定了 touchstart,touchmove,touchend事件,用来处理全局性的事件,比如滑动翻页 正常状态下: 用户在子元素上有交互动作时,默认状态下都是会冒泡到 ...
- 源码分析MySQL mysql_real_query函数
目录 目录 1 1. 前言 1 2. 调用路径 2 3. MAX_PACKET_LENGTH宏 2 4. DBUG_RETURN宏 3 5. COM_QUERY枚举值 3 6. mysql_query ...
- Zepto源代码分析一~核心方法
今天抽出时间复习了一下Zepto的源代码,依照自己的理解进行凝视. 欢迎大家拍砖. 源代码版本号:v1.1.4 源代码下载地址:http://zeptojs.com/ 分析总体代码之后,整理出架构图: ...
- Zepto源代码分析之二~三个API
因为时间关系:本次仅仅对这三个API($.camelCase.$.contains.$.each)方法进行分析 第一个方法变量转驼峰:$.camelCase('hello-world-welcome' ...
随机推荐
- spring 5.1.2 mvc RequestMappingHandlerMapping 调用handler过程
https://my.oschina.net/zhangxufeng/blog/2177464 https://www.jianshu.com/p/447826c28e37 Interceptors ...
- MATLAB2016a安装破解教程
首先,下载软件:下面是某博主的分享,可以下载软件. 链接:https://pan.baidu.com/s/1i6BgD8p 密码:17gg 第一步:安装软件 1,下载文件,得到R2016 ...
- Ajax获取Json多个集合并同时遍历
Ajax获取Json多个集合并同时遍历: 方法一.:将多个集合放入MAP集合. 后台:Servlet @Override protected void doPost(HttpServletReques ...
- TCP/IP(一)之开启计算机网络之路
阅读目录(Content) 一.局域网.广域网和Internet 1.1.局域网 1.2.广域网 1.3.Internet 二.计算机数据之间通信的过程 2.1.路由器的功能(转发收到的分组) 三.O ...
- Codeforces Round #554 (Div. 2) 1152A - Neko Finds Grapes
学了这么久,来打一次CF看看自己学的怎么样吧 too young too simple 1152A - Neko Finds Grapes 题目链接:"https://codeforces. ...
- Docker系列教程26-Docker Compose控制服务启动顺序
作者:周立 在生产中,往往有严格控制服务启动顺序的需求.然而Docker Compose自身并不具备该能力.要想实现启动顺序的控制,Docker Compose建议我们使用: wait-for-it ...
- Android 基本控件相关知识整理
Android应用开发的一项重要内容就是界面开发.对于用户来说,不管APP包含的逻辑多么复杂,功能多么强大,如果没有提供友好的图形交互界面,将很难吸引最终用户.作为一个程序员如何才能开发出友好的图形界 ...
- Git使用详细教程(4):git rm使用详解
我们使用git rm 文件名来进行删除文件的操作. git rm index.php这个命令把工作区的index.php删除并暂存了. 如何撤回已暂存的删除命令? 上图中已经给出了提示,使用git r ...
- deepin卸载mysql并安装设置mysql5.7
mysql完全卸载以及安全安装 完全卸载 sudo apt purge mysql-* sudo rm -rf /etc/mysql/ /var/lib/mysql sudo apt autoremo ...
- 小程序入口构造工具&二维码测试工具
小程序入口构造工具&二维码测试工具 本文将介绍我们小程序中隐藏的两个工具页面.原理虽不复杂,收益却实实在在,或许也能给诸君带来启发. 入口构造工具 痛点 PM&运营 投放链接 PM&a ...