zepto.js的事件处理
能够深入理解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有四个不同点:
- 它不会引起事件(比如表单提交)的默认行为
- trigger() 会操作 jQuery 对象匹配的所有元素,而 .triggerHandler() 只影响第一个匹配元素。
- 由 .triggerHandler() 创建的事件不会在 DOM 树中冒泡;如果目标元素不直接处理它们,则不会发生任何事情。
- 该方法的返回的是事件处理函数的返回值,而不是具有可链性的 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的事件处理的更多相关文章
- 学习zepto.js(对象方法)[5]
继续说. clone: 该方法不接收任何参数,会返回对象中的所有元素集合,但不会对象绑定的事件. var $temp = $("div").clone(); //并不接收任何参数. ...
- 学习zepto.js(对象方法)[3]
继续说zepto里attributes的相关操作. attr,removeAttr,prop这三个方法. attr(): 三种用途 get: 返回值为一个string字符串 $("<s ...
- 将jquery.shCircleLoader插件修改为zepto.js兼容
经过查阅资料zepto 和 jquery 的区别后发现是 (1)zepto.js 删去了 jquery 的 innerHeight() 和 innerWidth() 属性 (2)zepto.js和 ...
- scroll事件实现监控滚动条并分页显示示例(zepto.js)
scroll事件实现监控滚动条并分页显示示例(zepto.js ) 需求:在APP落地页上的底部位置显示此前其他用户的购买记录,要求此div盒子只显示3条半,但一页有10条,div内的滑动条滑到一页 ...
- 学习zepto.js(Hello World)
Zepto是一个轻量级的针对现代高级浏览器的JavaScript库, 它与jquery有着类似的api. 如果你会用jquery,那么你也会用zepto. 昨天听说了zepto.js,正好最近也比较闲 ...
- Zepto.js touch模块深入分析
目的:记录 Zepto.js touch模块 源码阅读 源码: // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zepto.js may be freely ...
- 使用backbone.js、zepto.js和trigger.io开发HTML5 App
为了力求运行速度快.响应迅即,我们推荐使用backbone.js和zepto.js. 为了让这个过程更有意思,我们开发了一个小小的示例项目,使用CSS重置样式.Backbone.js和带转场效果的几个 ...
- 移动开发js库Zepto.js应用详解
从哪里下载 Zepto 地址:http://zeptojs.com/ 中文版地址:http://www.css88.com/doc/zeptojs_api/ 这个问题看起来很蠢,从官网下载不就行了嘛! ...
- zepto.js + iscroll.js上拉加载 下拉加载的 移动端 新闻列表页面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...
随机推荐
- Android判断当前系统时间是否在指定时间的范围内(免消息打扰)
/** * 判断当前系统时间是否在指定时间的范围内 * * @param beginHour * 开始小时,例如22 * @param beginMin * 开始小时的分钟数,例如30 * @para ...
- 远程登录服务器执行cmd的Python脚本
import paramiko,os,sys ip = raw_input("input ip address :>>>") password = raw_inp ...
- nefu 117 素数定理
小明是一个聪明的孩子,对数论有着很浓烈的兴趣.他发现求1到正整数10n 之间有多少个素数是一个很难的问题,该问题的难以决定于n 值的大小.现在的问题是,告诉你n的值,让你帮助小明计算小于10n的素数的 ...
- Web前端性能优化教程05:网站样式和脚本
本文是Web前端性能优化系列文章中的第五篇,主要讲述内容:网站样式和脚本代码的放置位置.使用外部javascript和css.完整教程可查看:Web前端性能优化 一.将样式表放在顶部 可视性回馈的重要 ...
- 【转】HTTP中的长连接和短连接分析
1. HTTP协议与TCP/IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接.HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议.IP协议主要解决网络路由和寻址问 ...
- 【BZOJ-2599】Race 点分治
2599: [IOI2011]Race Time Limit: 70 Sec Memory Limit: 128 MBSubmit: 2590 Solved: 769[Submit][Status ...
- 【vijos1243】 生产产品
https://vijos.org/p/1243 (题目链接) 题意 一个产品的生产有m个步骤,一共n个机器人.机器人i完成步骤j的时间为T[i][j],每次当产品从一个机器人那里移动到另一个机器人那 ...
- 【poj1014】 Dividing
http://poj.org/problem?id=1014 (题目链接) 题意 给出有分别价值为1,2,3,4,5,6的6种物品,输入6个数字,表示相应价值的物品的数量,问一下能不能将物品分成两份, ...
- dedecms /include/filter.inc.php Local Variable Overriding
catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 filter.inc.php这个文件在系统配置文件之后,里面有forea ...
- dedecms /member/uploads_edit.php SQL Injection Vul
catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 Dedecms 5.3版本下的member/uploads_edit.p ...