能够深入理解zepto对事件的处理,那么整个JS的事件处理就应该差不多合格了,事件处理是JS语言的一个难点。

1. 首先来看$.event函数

JS中有很多事件,都是已经定义好了,我们直接调用就可以,例如熟悉的click事件,直接对dom绑定一个事件,点击该dom就能触发这个事件,但是有这样的场景:我点击一个dom,重新打开一个页面。按照常规,可以通过window.open来执行,也可以模拟一个连接,在这个链接上绑定click,之后触发这个click事件。代码如下:

var a = document.createElement("a");
a.setAttribute("href", url);
a.setAttribute("target", "_blank");
a.setAttribute("id", "openwin");
document.body.appendChild(a);
//模拟点击事件
var m = document.createEvent("MouseEvents"); //FF的处理
m.initEvent("click", true, true);
a.dispatchEvent(m);

在zepto.js的ajax源码中,有很多注册事件,这些事件都是通过下来代码来完成的。

function triggerAndReturn(context, eventName, data) {
//步骤1:注册事件
var event = $.Event(eventName)
//步骤2:分发事件
$(context).trigger(event, data)
return !event.defaultPrevented
}
在注册和分发事件中,有三个步骤,对于与三个函数:
document.createEvent()  //新建
event.initEvent() //初始化
this.dispatchEvent() //元素触发事件

来看看$.event源码:

$.Event = function(type, props) {
if (!isString(type)) props = type, type = props.type
//click,mousedown,mouseup,mousemove的事件是MouseEvents,其他的是Events。
var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
//event.initEvent(eventType,canBubble,cancelable)
//eventType 字符串值。事件的类型。
//canBubble 事件是否起泡。
//cancelable 是否可以用 preventDefault() 方法取消事件。把bubbles从props中过滤出来,单独处理。
if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
event.initEvent(type, bubbles, true)
return compatible(event)
} /*
stopImmediatePropagation方法作用在当前节点以及事件链上的所有后续节点上。
目的是在执行完当前事件处理程序之后,停止当前节点以及所有后续节点的事件处理程序的运行。
stopPropagation方法作用在后续节点上,目的在执行完绑定到当前元素上的所有事件处理程序之后,停止执行所有后续节点的事件处理程序
*/
eventMethods = {
preventDefault: 'isDefaultPrevented',
stopImmediatePropagation: 'isImmediatePropagationStopped',
stopPropagation: 'isPropagationStopped'
}
function compatible(event, source) {
if (source || !event.isDefaultPrevented) {
source || (source = event)
/*
给event注册6个函数,默认[isDefaultPrevented,isImmediatePropagationStopped,isPropagationStopped] = false,
执行preventDefault之后,对应的preventDefault = {return true;}
*/
$.each(eventMethods, function(name, predicate) {
var sourceMethod = source[name]
event[name] = function(){
this[predicate] = returnTrue
return sourceMethod && sourceMethod.apply(source, arguments)
}
event[predicate] = returnFalse
})
//给isDefaultPrevented赋值
if (source.defaultPrevented !== undefined ? source.defaultPrevented :
'returnValue' in source ? source.returnValue === false :
source.getPreventDefault && source.getPreventDefault())
event.isDefaultPrevented = returnTrue
}
return event
}

再来看看$.trigger事件:

function fix(event) {
if (!('defaultPrevented' in event)) {
event.defaultPrevented = false
var prevent = event.preventDefault
//通过preventDefault取消事件的触发。
event.preventDefault = function() {
this.defaultPrevented = true
prevent.call(this)
}
}
}
$.fn.trigger = function(event, data){
if (typeof event == 'string') event = $.Event(event)
//添加preventDefaulted成员和重载preventDefault事件。
fix(event)
event.data = data
return this.each(function(){
//是dom节点都会有dispatchEvent事件,不是dom,如果有dispatchEvent事件也会执行。
if('dispatchEvent' in this) this.dispatchEvent(event)
})
}

还有一个triggerHandler事件,它与trigger有四个不同点:

  1. 它不会引起事件(比如表单提交)的默认行为
  2. trigger() 会操作 jQuery 对象匹配的所有元素,而 .triggerHandler() 只影响第一个匹配元素。
  3. 由 .triggerHandler() 创建的事件不会在 DOM 树中冒泡;如果目标元素不直接处理它们,则不会发生任何事情。
  4. 该方法的返回的是事件处理函数的返回值,而不是具有可链性的 jQuery 对象。此外,如果没有处理程序被触发,则这个方法返回 undefined。

这个后面我们再讨论。

2.事件对象

  用JS原生态的绑定事件很easy,而zepto对绑定事件进行重重封装,最明显的莫过于event对象,常规绑定事件。

    //每个element都有一个_zid来判断该element上已经绑定了几个事件。
var id = zid(element),
set = (handlers[id] || (handlers[id] = []))
eachEvent(events, fn, function(event, fn){
//如果没有事件委托,add只有element, events, fn三个参数
//element: 元素节点 events=["click","mouseup"...]
//fn:函数名或者匿名函数。
var delegate = getDelegate && getDelegate(fn, event),
callback = delegate || fn
var proxyfn = function (event) {
var result = callback.apply(element, [event].concat(event.data))
//callback返回为false,阻止默认事件。
if (result === false) event.preventDefault()
return result
}
/*
event = {
e: 事件名称
ns: 事件命名空间的对象
data: 参数
}
*/
var handler = $.extend(parse(event),
{
fn: fn,
proxy: proxyfn,
sel: selector,
del: delegate,
i: set.length
})
set.push(handler)
element.addEventListener(handler.e, proxyfn, capture)
})
}

委托绑定事件:

$.fn.delegate = function(selector, event, callback){
//委托事件不需要冒泡到父节点,只针对特定元素。
var capture = false
if(event == 'blur' || event == 'focus'){
if($.iswebkit)
event = event == 'blur' ? 'focusout' : event == 'focus' ? 'focusin' : event
else
capture = true
}
return this.each(function(i, element){
add(element, event, callback, selector, function(fn){
return function(e){
var evt,
match = $(e.target).closest(selector, element).get(0)
//匹配到特定的元素
if (match) {
evt = $.extend(createProxy(e),
{ currentTarget: match,
liveFired: element
})
return fn.apply(match, [evt].concat([].slice.call(arguments, 1)))
}
}
}, capture)
})
}

还有一种绑定事件,只绑定一次,

$.fn.one = function(event, callback){
return this.each(function(i, element){
//没有子元素选择参数
add(this, event, callback, null, function(fn, type){
return function(){
var result = fn.apply(element, arguments)
//触发之后,删除该事件。
remove(element, type, fn)
return result
}
})
})

 

zepto.js的事件处理的更多相关文章

  1. 学习zepto.js(对象方法)[5]

    继续说. clone: 该方法不接收任何参数,会返回对象中的所有元素集合,但不会对象绑定的事件. var $temp = $("div").clone(); //并不接收任何参数. ...

  2. 学习zepto.js(对象方法)[3]

    继续说zepto里attributes的相关操作. attr,removeAttr,prop这三个方法. attr(): 三种用途 get: 返回值为一个string字符串 $("<s ...

  3. 将jquery.shCircleLoader插件修改为zepto.js兼容

    经过查阅资料zepto 和 jquery 的区别后发现是 (1)zepto.js  删去了 jquery 的 innerHeight() 和 innerWidth() 属性  (2)zepto.js和 ...

  4. scroll事件实现监控滚动条并分页显示示例(zepto.js)

    scroll事件实现监控滚动条并分页显示示例(zepto.js  ) 需求:在APP落地页上的底部位置显示此前其他用户的购买记录,要求此div盒子只显示3条半,但一页有10条,div内的滑动条滑到一页 ...

  5. 学习zepto.js(Hello World)

    Zepto是一个轻量级的针对现代高级浏览器的JavaScript库, 它与jquery有着类似的api. 如果你会用jquery,那么你也会用zepto. 昨天听说了zepto.js,正好最近也比较闲 ...

  6. Zepto.js touch模块深入分析

    目的:记录 Zepto.js touch模块 源码阅读 源码: // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zepto.js may be freely ...

  7. 使用backbone.js、zepto.js和trigger.io开发HTML5 App

    为了力求运行速度快.响应迅即,我们推荐使用backbone.js和zepto.js. 为了让这个过程更有意思,我们开发了一个小小的示例项目,使用CSS重置样式.Backbone.js和带转场效果的几个 ...

  8. 移动开发js库Zepto.js应用详解

    从哪里下载 Zepto 地址:http://zeptojs.com/ 中文版地址:http://www.css88.com/doc/zeptojs_api/ 这个问题看起来很蠢,从官网下载不就行了嘛! ...

  9. zepto.js + iscroll.js上拉加载 下拉加载的 移动端 新闻列表页面

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...

随机推荐

  1. display~

  2. 【BZOJ 1503】【NOI 2004】郁闷的出纳员

    $Splay$模板题. 复习一下伸展树的模板. 一定不要忘了push啊!!! 对于减工资后删掉员工的操作,我选择插入一个$min+delta_{减少的工资}$的节点,把它$Splay$到根,砍掉它自己 ...

  3. Ext-进度条

    1.progress使用 Ext.MessageBox.progress('请等待',msg:'读取数据中……'); 真实案例 tqbtnNews:function(){ var me = this; ...

  4. js-处理div设置的编辑框处理焦点定位追加内容

    具体实现方法如下: 首先要让DIV启用编辑模式 <div contenteditable=true id="divTest"></div> 通过设定cont ...

  5. iis Server Error in '/' Application

    1.开始-运行-cmd-输入cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727-回车-aspnet_regiis.exe -i 回车 2.如果不是检查链接 ...

  6. 【POJ 1981 】Circle and Points

    当两个点距离小于直径时,由它们为弦确定的一个单位圆(虽然有两个圆,但是想一想知道只算一个就可以)来计算覆盖多少点. #include <cstdio> #include <cmath ...

  7. 【BZOJ-4059】Non-boring sequences 线段树 + 扫描线 (正解暴力)

    4059: [Cerc2012]Non-boring sequences Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 440  Solved: 16 ...

  8. 【poj2942】 Knights of the Round Table

    http://poj.org/problem?id=2942 (题目链接) 题意 有n个骑士要去参加圆桌会议,他们将围成一圈,想要他们不打架,当且仅当参加圆桌会议的骑士数为奇数并且相邻的两个骑士不互相 ...

  9. BZOJ3295 [Cqoi2011]动态逆序对

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  10. Jenkins企业版与CloudBees

    Jenkins企业版由CloudBess提供! 参考 https://www.cloudbees.com/ http://www.infoq.com/cn/news/2012/01/cloudbees ...