jQuery的实现原理的模拟代码 -3 事件处理


Posted in Javascript onAugust 03, 2010

在对象的私有扩展对象上,专门增加了一个名为 events 的事件管理对象,在这个对象上每种事件分别对应一个同名的属性,这个属性的值是一个数组,针对这个事件的处理程序依次压入这个数组中,构成一个事件处理的列表。自定义的事件处理函数即被压入这个列表中。

在事件触发的时候,通过注册的匿名函数来执行 jQuery.event.handle ,由于使用了闭包,所以在这个函数中的 this 就是事件源对象,通过这个事件源对象找到对象的私有扩展数据,然后在 events 中找到对应的事件处理程序列表,最后,依次执行。

/// <reference path="jQuery-core.js" /> 
// #2076 
// 用于生成事件处理函数的 id 
jQuery.guid = 1; 
// jQuery 的事件对象 
jQuery.event = { // # 1555 
// 为对象增加事件 
// elem 增加事件的元素, type 事件的名称, handler 事件处理程序, data 事件相关的数据 
add: function (elem, type, handler, data) { 
var handleObjIn, handleObj; 
// 确认函数有一个唯一的 ID 
if (!handler.guid) { 
handler.guid = jQuery.guid++; 
} 
// 取得这个元素所对应的缓存数据对象 
var elemData = jQuery.data(elem); 
// 取得元素对应的缓存对象上的事件对象和所有事件共用的处理程序 
var events = elemData.events = elemData.events || {}; 
var eventHandle = elemData.handle; 
// 是否已经有事件处理函数 handle 只有一个,都是使用 jQuery.event.handle 
// 通过使用闭包,使得这个函数引用当前的事件对象,参数。 
if (!eventHandle) { 
elemData.handle = eventHandle = function () { 
return jQuery.event.handle.apply(eventHandle.elem, arguments); 
}; 
} 
// 使得闭包处理程序可以找到事件源对象 
eventHandle.elem = elem; 
// 
handleObj = { handler: handler, data: data}; 
handleObj.namespace = ""; handleObj.type = type; 
handleObj.guid = handler.guid; 
// 每种事件可以有一系列的处理程序,数组形式 
var handlers = events[type], 
special = jQuery.event.special[type] || {}; 
// Init the event handler queue 
if (!handlers) { 
handlers = events[type] = []; 
// Check for a special event handler 
// Only use addEventListener/attachEvent if the special 
// events handler returns false 
// 完成实际的事件注册 
// 实际的事件处理函数是 eventHandle 
if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) { 
// Bind the global event handler to the element 
if (elem.addEventListener) { 
elem.addEventListener(type, eventHandle, false); 
} else if (elem.attachEvent) { 
elem.attachEvent("on" + type, eventHandle); 
} 
} 
} 
// 自定义的处理函数在一个堆栈中,以后 jQuery.event.handle 到这里找到实际的处理程序 
handlers.push(handleObj); 
// Nullify elem to prevent memory leaks in IE 
elem = null; 
}, 
global: {}, 
// 真正的事件处理函数, 
// 由于是通过 return jQuery.event.handle.apply(eventHandle.elem, arguments) 调用的 
// 所以,此时的 this 就是事件源对象,event 是事件参数 
handle: function (event) { // 1904 
var all, handlers, namespaces, namespace, events; 
event = window.event; 
event.currentTarget = this; 
// 在当前的事件对象上找到事件处理列表 
var events = jQuery.data(this, "events"), handlers = events[event.type]; 
if (events && handlers) { 
// Clone the handlers to prevent manipulation 
handlers = handlers.slice(0); 
for (var j = 0, l = handlers.length; j < l; j++) { 
var handleObj = handlers[j]; 
// 取得注册事件时保存的参数 
event.handler = handleObj.handler; 
event.data = handleObj.data; 
event.handleObj = handleObj; 
var ret = handleObj.handler.apply(this, arguments); 
} 
} 
return event.result; 
}, 
// #2020 
special: {} 
} 
// bind 函数定义 
jQuery.fn.bind = function( type, fn) 
{ 
var handler = fn; 
// 调用 jQuery.event.add 添加事件 
for (var i = 0, l = this.length; i < l; i++) { 
jQuery.event.add(this[i], type, handler); 
} 
return this; 
} 
jQuery.fn.unbind = function (type, fn) { 
// Handle object literals 
if (typeof type === "object" && !type.preventDefault) { 
for (var key in type) { 
this.unbind(key, type[key]); 
} 
} else { 
for (var i = 0, l = this.length; i < l; i++) { 
jQuery.event.remove(this[i], type, fn); 
} 
} 
return this; 
} 
// click 事件的注册方法 
jQuery.fn.click = function (fn) { 
this.bind("click", fn); 
return this; 
}

这样,对于页面上的 id 为 msg 的元素,就可以通过下面的代码注册一个 click 事件处理函数。

// 事件操作 
$("#msg").click( 
function () { 
alert(this.innerHTML); 
} 
);
Javascript 相关文章推荐
jQuery使用技巧简单汇总
Apr 18 Javascript
利用CSS、JavaScript及Ajax实现高效的图片预加载
Oct 16 Javascript
JavaScript中合并数组的N种方法
Sep 16 Javascript
jquery带有索引按钮且自动轮播切换特效代码分享
Sep 15 Javascript
Ajax和Comet技术总结
Feb 19 Javascript
详解vue express启动数据服务
Jul 05 Javascript
Vue2几种常见开局方式详解
Sep 09 Javascript
浅谈Vuex@2.3.0 中的 state 支持函数申明
Nov 22 Javascript
vue-cli3.0使用及部分配置详解
Aug 29 Javascript
简单了解JavaScript中常见的反模式
Jun 21 Javascript
Vue实现商品分类菜单数量提示功能
Jul 26 Javascript
Node Mongoose用法详解【Mongoose使用、Schema、对象、model文档等】
May 13 Javascript
SlideView 图片滑动(扩展/收缩)展示效果
Aug 01 #Javascript
JavaScript和ActionScript的交互实现代码
Aug 01 #Javascript
JavaScript判断窗口是否最小化的代码(跨浏览器)
Aug 01 #Javascript
jquery下onpropertychange事件的绑定方法
Aug 01 #Javascript
关于this和self的使用说明
Aug 01 #Javascript
ajax 缓存 问题 requestheader
Aug 01 #Javascript
parseInt parseFloat js字符串转换数字
Aug 01 #Javascript
You might like
用PHP实现 上一篇、下一篇的代码
2012/09/29 PHP
php登录超时检测功能实例详解
2017/03/21 PHP
动态载入/删除/更新外部 JavaScript/Css 文件的代码
2010/07/03 Javascript
actionscript与javascript的区别
2011/05/25 Javascript
Javascript类定义语法,私有成员、受保护成员、静态成员等介绍
2011/12/08 Javascript
获取中文字符串的实际长度代码
2014/06/05 Javascript
Enter回车切换输入焦点实现思路与代码兼容各大浏览器
2014/09/01 Javascript
javascript三元运算符用法实例
2015/04/16 Javascript
jQuery实现的纵向下拉菜单实例详解【附demo源码下载】
2016/07/09 Javascript
BootStrap 附加导航组件
2016/07/22 Javascript
KnockoutJS 3.X API 第四章之数据控制流with绑定
2016/10/10 Javascript
解决前端跨域问题方案汇总
2016/11/20 Javascript
angularjs $http实现form表单提交示例
2017/06/09 Javascript
JS去掉字符串中所有的逗号
2017/10/18 Javascript
Vue 仿QQ左滑删除组件功能
2018/03/12 Javascript
Vue项目数据动态过滤实践及实现思路
2018/09/11 Javascript
京东优选小程序的实现代码示例
2020/02/25 Javascript
[01:01:42]Secret vs Optic Supermajor 胜者组 BO3 第二场 6.4
2018/06/05 DOTA
python和C语言混合编程实例
2014/06/04 Python
Python实现子类调用父类的方法
2014/11/10 Python
Python+OpenCV目标跟踪实现基本的运动检测
2018/07/10 Python
Python修改文件往指定行插入内容的实例
2019/01/30 Python
Python 正则表达式爬虫使用案例解析
2019/09/23 Python
Python jieba结巴分词原理及用法解析
2020/11/05 Python
纯css3制作煽动翅膀的蝴蝶的示例
2018/04/23 HTML / CSS
纯css3实现宠物小鸡实例代码
2018/10/08 HTML / CSS
戴森香港官方网站:Dyson香港
2021/02/11 全球购物
幼儿园毕业教师感言
2014/02/21 职场文书
桥梁工程专业求职信
2014/04/21 职场文书
小学优秀辅导员事迹材料
2014/05/11 职场文书
销售团队激励口号
2014/06/06 职场文书
2014年司机工作总结
2014/11/21 职场文书
2014年招商工作总结
2014/11/22 职场文书
2014年乡镇人大工作总结
2014/11/25 职场文书
2015年办公室文秘工作总结
2015/04/30 职场文书
助学金申请书该怎么写?
2019/07/16 职场文书