非常适合新手的jq/zepto源码分析06 -- 事件模型
复习下事件的有关内容:
1.现在用的绑定/删除:
obj.addEventListener(type,fn,false)
obj.removeEventListener(type)
obj.attachEvent(type,fn) //ie
obj.detachEvent(type)
2.js的event对象
type : 事件类型
srcElement/target : 事件源
button : 如果是鼠标按下,则 1左键 2右键 4中间滚轮 多个键则相加按下的所有值。 firfox 0左键1右键2滚轮
clientX/clientY : 鼠标相当于文档的位置
offsetX/offsetY/layerX/layerY : 鼠标相对于源元素位置
altKey/ctrKey/shiftkey : alt / ctr / shift 是否按下
keyCode : 键盘事件的 返回键的对应值
relateTarget : {fromElement/toElement} 鼠标进入离开时候的相关元素
cancelBubble/stopPropagtion() : 阻止冒泡事件
screenX/screenY : 相对于显示器的位置
returnValue/preventDefault() : 阻止元素默认事件
差不多就这么多,在不行就去百度搜文档。
$.event = { add: add, remove: remove }
直接绑定在对象上面了
function add(element, events, fn, data, selector, delegator, capture){
//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)
//parse(e) 解析事件 例如 click.cname -->{e:click,ns:cname}
var handler = parse(event)
handler.fn = fn
handler.sel = selector
// 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){
//处理event事件
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))
})
}
_zid : 每一个绑定事件的元素都有一个唯一ID
handlers : 所有的事件回调句柄都会以 ID 为键值保存在 handles里面,handles[_zid] = [handle1,handle2,...]
headler : { fn : 函数,del : 回调, i : index位置 , sel : css选择器 , e : 当前事件名称 , proxy :代理函数(执行的函数) }
function remove(element, events, fn, selector, capture){
//对应的事件ID
var id = zid(element)
;(events || '').split(/\s/).forEach(function(event){
//findHandlers 找到要移除的句柄 返回一个数组
findHandlers(element, event, fn, selector).forEach(function(handler){
//移除句柄
delete handlers[id][handler.i]
if ('removeEventListener' in element)
//接触绑定的该函数
element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
})
})
}
$.proxy = function(fn, context) {
var args = (2 in arguments) && slice.call(arguments, 2)
if (isFunction(fn)) {
//fn如果是函数 就相当于proxyFn fn.apply(conteng,args) proxyFn 加了个位置ID
var proxyFn = function(){ return fn.apply(context, args ? args.concat(slice.call(arguments)) : arguments) }
proxyFn._zid = zid(fn)
return proxyFn
} else if (isString(context)) {
if (args) {
args.unshift(fn[context], fn)
return $.proxy.apply(null, args)
} else {
return $.proxy(fn[context], fn)
}
} else {
throw new TypeError("expected function")
}
}
$.fn.on = function(event, selector, data, callback, one){
var autoRemove, delegator, $this = this
//event是数组或者类数组
if (event && !isString(event)) {
$.each(event, function(type, fn){
//迭代执行该函数
$this.on(type, selector, data, fn, one)
})
return $this
}
//elem.on('click',fn) 绑定事件
if (!isString(selector) && !isFunction(callback) && callback !== false)
callback = data, data = selector, selector = undefined
//elem.on('click','a',fn) 事件委托
if (callback === undefined || data === false)
callback = data, data = undefined
if (callback === false) callback = returnFalse
return $this.each(function(_, element){
//回调函数,当执行时候就移除绑定的函数 然后执行改callback
if (one) autoRemove = function(e){
remove(element, e.type, callback)
return callback.apply(this, arguments)
}
if (selector) delegator = function(e){
var evt, match = $(e.target).closest(selector, element).get(0)
if (match && match !== element) {
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)
})
}
bind,one,delegate,live全都是继承了并执行on函数
$.fn.off = function(event, selector, callback){
var $this = this
if (event && !isString(event)) {
$.each(event, function(type, fn){
$this.off(type, selector, fn)
})
return $this
}
if (!isString(selector) && !isFunction(callback) && callback !== false)
callback = selector, selector = undefined
if (callback === false) callback = returnFalse
return $this.each(function(){
remove(this, event, callback, selector)
})
}
所有的一定事件都是继承并执行该函数
$.fn.trigger = function(event, args){
event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
event._args = args
return this.each(function(){
// focus(),blur()直接调用
if (event.type in focus && typeof this[event.type] == "function") this[event.type]()
// items in the collection might not be DOM elements
//自定义的 事件 直接用 用creatEvent的事件可以指定用dispatcheEvent(e)
else if ('dispatchEvent' in this) this.dispatchEvent(event)
//获取到绑定的事件并执行,通过event找到 在 Handers中到到对应的函数 handlers.proxy执行
else $(this).triggerHandler(event, args)
})
}
手动触发事件
$.Event = function(type, props) {
if (!isString(type)) props = type, type = props.type
var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
event.initEvent(type, bubbles, true)
return compatible(event)
}
//创建一个Event对象,并且初始化事件对象,可以去看看creareEvent文档
代码仅供参考,具体功能可以自己扩展。
http://www.cnblogs.com/jiebba/p/6529854.html
http://www.cnblogs.com/jiebba 我的博客,来看吧!
如果有错误,请留言修改下 哦!
非常适合新手的jq/zepto源码分析06 -- 事件模型的更多相关文章
- 非常适合新手的jq/zepto源码分析08---ajax的封装
1.现在看看对JSONP的封装 $.ajaxJSONP = function(options, deferred){ if (!('type' in options)) return $.ajax(o ...
- 非常适合新手的jq/zepto源码分析07---ajax的封装
复习下ajax吧! 1.创建XMLHttpRequest对象 xmlhttp=new XMLHttpRequest(); xmlhttp=new ActiveXObject("Microso ...
- 非常适合新手的jq/zepto源码分析05
zepto的原型 $.fn 属性: constructor //构造行数 forEach: emptyArray.forEach, //都是原生数组的函数reduce: emptyArray.re ...
- 非常适合新手的jq/zepto源码分析03
zepto.fragment = function(html, name, properties) { var dom, nodes, container // 如果是简单的标签<div> ...
- 非常适合新手的jq/zepto源码分析04
$.extend = function(target){ var deep, args = slice.call(arguments, 1) if (typeof target == 'boolean ...
- 非常适合新手的jq/zepto源码分析01
(function(global, factory) { // 查看这里是不是定义成模块,如果定义模块就返回 一个模块 if (typeof define === 'function' &&a ...
- 非常适合新手的jq/zepto源码分析02
function isPlainObject(obj) { return isObject(obj) && !isWindow(obj) && Object.getPr ...
- zepto源码分析系列
如果你也开发移动端web,如果你也用zepto,应该值得你看看.有问题请留言. Zepto源码分析-架构 Zepto源码分析-zepto(DOM)模块 Zepto源码分析-callbacks模块 Ze ...
- 一个普通的 Zepto 源码分析(二) - ajax 模块
一个普通的 Zepto 源码分析(二) - ajax 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块,以 ...
随机推荐
- 题解报告:hdu 1010 Tempter of the Bone
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010 Problem Description The doggie found a bone in a ...
- Android 性能优化(3)性能工具之「调试 GPU 过度绘制」Debug GPU Overdraw Walkthrough-查看哪些view过度绘制了
Debug GPU Overdraw Walkthrough 1.In this document Prerequisites Visualizing Overdraw You should also ...
- 全面学习ORACLE Scheduler特性(12)使用Windows和Window Groups
七.使用Windows 此Windows非彼Windows,通常说的Windows是指盖首富的操作系统,而此处所说的Windows,是指SCHEDULER特性中的一个子项.在SCHEDULER中,WI ...
- 397 Integer Replacement 整数替换
给定一个正整数 n,你可以做如下操作:1. 如果 n 是偶数,则用 n / 2替换 n.2. 如果 n 是奇数,则可以用 n + 1或n - 1替换 n.n 变为 1 所需的最小替换次数是多少?示例 ...
- P1165 日志分析
题目描述 M 海运公司最近要对旗下仓库的货物进出情况进行统计.目前他们所拥有的唯一记录就是一个记录集装箱进出情况的日志.该日志记录了两类操作:第一类操作为集装箱入库操作,以及该次入库的集装箱重量:第二 ...
- App保持登录状态的常用方法
我们在使用App时,一次登录后App如果不主动退出登录或者清除数据,App会在很长一段时间内保持登录状态,或者让用户感觉到登录一次就不用每次都输入用户密码才能进行登录.银行.金融涉及到支付类的App一 ...
- git分支拉取
假设你已经配置好了各种SSH Key之类并熟悉基本的git创建分支.提交分支命令.比如共有2个分支,自己在一台未配置origin电脑上想要拉取某个分支(dev)到本地.步骤如下:1.新建git项目 与 ...
- DIV水平 垂直居中CSS
/*实现一.原理:要让div等块级元素水平和垂直居中,必需知道该div等块级元素的宽度和高度,然后设置位置为绝对位置,距离页面窗口左边框和上边框的距离设置为50%,这个50%就是指页面窗口的宽度和高度 ...
- 史上最大型广告欺诈活动Methbot:黑客是如何每天赚到500万美元的
根据国外安全专家的最新报告,有一群黑客正在对美国的知名企业和媒体机构进行广告欺诈活动,而这群黑客每天都可以从中赚取三百万到五百万美金. 是的,你没看错,这绝对是人类历史上最牛X的恶意广告欺诈活动!不过 ...
- 2-2 列表推导同 filter 和 map 的比较
列表推导同 filter 和 map 的比较 参考廖雪峰的文档: filter()函数:用于过滤序列. filter()接收一个函数和一个序列.把传入的函数依次作用于传入的序列的每个元素,根据返回值是 ...