正文
作者打字速度实在不咋地,源码部分就用图片代替了,都是截图,本文讲解的Zepto版本是1.2.0,在该版本中的event模块与1.1.6基本一致。此文的fastclick理解上在看过博客园各个大神的文章后对我确实有很大的帮助,当然,我的某些观点可能不是很准确甚至有错误,欢迎讨论,白天基本在线。
zepto的event
可以结合上一篇JavaScript事件详解-原生事件基础(一)综合考虑
源码暂且不表,github里还有中文网站都能下到最新版的zepto。整个event模块不长,274行,我们可以看到,整个event模块,事件绑定核心就是on和off,还有一个trigger用来触发,类观察者模式,可以先看看汤姆大叔的深入理解JavaScript系列(32):设计模式之观察者模式,其余皆为实现的处理函数。
首先来个demo:
$("#btn").on("click",function(event){
console.log(event);
})
一个简单的click事件监听示例。
根据event模块中对于事件的使用来看:
on为开始(add)
可以看到,绑定函数有五个参数:
- event:事件类型,可以通过空格的字符串方式添加("click mousedown"),或者事件类型为键,函数为值的方式({click:function(),mousedown:function()})。
- selector:事件委托的节点选择器,可不传
- data:事件处理程序中的event.data属性
- callback:事件处理程序的回调函数
- one:绑定事件后,只触发一次回调
根据参数,我们可以很轻易的将on分为几部分(上图所示):
- 递归序列,处理event为键值对的情况
- 简写方式,如果只是简单的事件和回调的话($("#btn").on("click",function(){})),one参数不参与简写形式,有单独的one()方法。
- 循环zepto对象,因为这里的$this是zepto.init之后生成的对象,这里对于one和selector进行了autoRemove(只触发一次回调),delegetor(事件代理),然后是add(事件注册)
autoRemove,如果one为true,也就是只想使用一次,那么使用remove,并通过apply,给callback设立event对象;
而delegator中,如果selector是绑定元素的子节点,zepto以event.target为目标元素,判断是否触发节点的父级和传入的selector一致,上下文是遍历之后的节点。然后创建一个该事件对象的副本(createProxy),返回compatible()函数处理的event,当然,最后都会通过add()来进行注册:
首先是zid,zepto里面有个handlers对象,用于存放处理过的事件对象,_zid初始值为1,每次会按照值存入handlers,并且修改event对象中的_zid,每次存入的是一次绑定的所有事件:
因为每次使用$()创建的zepto对象都是新的,用handlers建立队列才能更好的进行管理。
之后就是对于以空白字符形式(/\s/)进行分割的字符串的处理,内部创建了handle,注意其parse方法是内部方法,而不是Date.parse()。
前面也说过,冒泡事件会有副作用,mouseover和mouseout,如果只是简单的节点,没有问题,但有了子节点之后。原先监听父节点的事件,