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 相关文章推荐
javawscript 三级菜单的实现原理
Jul 01 Javascript
javascript 计算两个整数的百分比值
Dec 26 Javascript
JavaScript常用全局属性与方法记录积累
Jul 03 Javascript
jquery复选框全选/取消示例
Dec 30 Javascript
禁用Tab键JS代码兼容Firefox和IE
Apr 18 Javascript
对new functionName()定义一个函数的理解
May 22 Javascript
JS中frameset框架弹出层实例代码
Apr 01 Javascript
JS中from 表单序列化提交的代码
Jan 20 Javascript
angular ng-click防止重复提交实例
Jun 16 Javascript
jQuery中实现text()的方法
Apr 04 jQuery
详解vue 在移动端体验上的优化解决方案
May 20 Javascript
详解mpvue开发微信小程序基础知识
Sep 23 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+JS+rsa数据加密传输实现代码
2011/03/23 PHP
thinkPHP5.0框架环境变量配置方法
2017/03/17 PHP
Yii2.0框架behaviors方法使用实例分析
2019/09/30 PHP
fckeditor 获取文本框值的实现代码
2009/02/09 Javascript
Jquery ThickBox插件使用心得(不建议使用)
2010/09/08 Javascript
从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件
2011/02/23 Javascript
myEvent.js javascript跨浏览器事件框架
2011/10/24 Javascript
Extjs4 关于Store的一些操作(加载/回调/添加)
2013/04/18 Javascript
对之前写的jquery分页做下升级
2014/06/19 Javascript
JQuery 设置checkbox值二次无效的解决方法
2016/07/22 Javascript
基于vuejs+webpack的日期选择插件
2020/05/21 Javascript
WebView启动支付宝客户端支付失败的问题小结
2017/01/11 Javascript
js学习总结之dom2级事件基础知识详解
2017/07/27 Javascript
js canvas实现简单的图像扩散效果
2020/06/28 Javascript
JavaScript中Require调用js的实例分享
2017/10/27 Javascript
如何解决vue2.0下IE浏览器白屏问题
2018/09/13 Javascript
深入理解react 组件类型及使用场景
2019/03/07 Javascript
在JavaScript中如何访问暂未存在的嵌套对象
2019/06/18 Javascript
vue实现从外部修改组件内部的变量的值
2020/07/30 Javascript
zbar解码二维码和条形码示例
2014/02/07 Python
Python2.x利用commands模块执行Linux shell命令
2016/03/11 Python
解决Python requests 报错方法集锦
2017/03/19 Python
Python 绘制可视化折线图
2020/07/22 Python
Python configparser模块应用过程解析
2020/08/14 Python
一套英文Java笔试题面试题
2016/04/21 面试题
口腔工艺技术专业毕业生自荐信
2013/09/27 职场文书
电脑教师的自我评价
2013/12/18 职场文书
关于元旦的广播稿
2014/02/16 职场文书
会计师职业生涯规划范文
2014/02/18 职场文书
《沉香救母》教学反思
2014/04/19 职场文书
监察建议书
2015/02/04 职场文书
毕业论文致谢部分怎么写
2015/05/14 职场文书
单位更名证明
2015/06/18 职场文书
我的生日感言
2015/08/03 职场文书
2016年社区服务活动总结
2016/04/06 职场文书
MySQL 8.0 驱动与阿里druid版本兼容问题解决
2021/07/01 MySQL