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 easyui的tabs使用时的问题
Mar 23 Javascript
jquery获取元素值的方法(常见的表单元素)
Nov 15 Javascript
快速解决jquery之get缓存问题的最简单方法介绍
Dec 19 Javascript
jquery自动将form表单封装成json的具体实现
Mar 17 Javascript
使用pjax实现无刷新更改页面url
Feb 05 Javascript
浅谈javascript基础之客户端事件驱动
Jun 10 Javascript
一个例子轻松学会Vue.js
Jan 02 Javascript
Angualrjs 表单验证的两种方式(失去焦点验证和点击提交验证)
May 09 Javascript
Underscore之Array_动力节点Java学院整理
Jul 10 Javascript
angularjs 获取默认选中的单选按钮的value方法
Feb 28 Javascript
vue2.0 element-ui中el-select选择器无法显示选中的内容(解决方法)
Aug 24 Javascript
mpvue实现微信小程序快递单号查询代码
Apr 03 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
IIS6的PHP最佳配置方法
2007/03/19 PHP
php 异常处理实现代码
2009/03/10 PHP
PHP下操作Linux消息队列完成进程间通信的方法
2010/07/24 PHP
PHP 字符串正则替换函数preg_replace使用说明
2011/07/15 PHP
手把手教你打印出PDF(关于fpdf的简单应用)
2013/06/25 PHP
PHP实现的MongoDB数据库操作类分享
2014/05/12 PHP
PHP IDE PHPStorm配置支持友好Laravel代码提示方法
2015/05/12 PHP
PHP下载生成的csv文件及问题总结
2015/08/06 PHP
分享php邮件管理器源码
2016/01/06 PHP
PHP 生成微信红包代码简单
2016/03/25 PHP
图文详解phpstorm配置Xdebug进行调试PHP教程
2016/06/13 PHP
jquery表单验证使用插件formValidator
2012/11/10 Javascript
js onload处理html页面加载之后的事件
2013/10/30 Javascript
nodejs事件的监听与触发的理解分析
2015/02/12 NodeJs
javascript常见数据验证插件大全
2015/08/03 Javascript
JS根据生日月份和日期计算星座的简单实现方法
2016/11/24 Javascript
Vue实现双向数据绑定
2017/05/03 Javascript
NodeJS 中Stream 的基本使用
2018/07/30 NodeJs
Vue项目实现换肤功能的一种方案分析
2019/08/28 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
2020/03/08 Javascript
学习 Vue.js 遇到的那些坑
2021/02/02 Vue.js
python2.6.6如何升级到python2.7.14
2018/04/08 Python
解决pip install psycopg2出错问题
2020/07/09 Python
米兰必去买手店排行榜首位:Antonioli
2016/09/11 全球购物
美国球鞋寄卖网站:Stadium Goods
2018/05/09 全球购物
高中生校园生活自我评价
2013/09/19 职场文书
高考自主招生自荐信
2013/10/20 职场文书
银行个人求职自荐信范文
2013/12/16 职场文书
小学生节约用水倡议书
2014/05/15 职场文书
诚信考试标语
2014/06/24 职场文书
教师工作自我鉴定范文
2014/09/14 职场文书
2014年房地产个人工作总结
2014/12/20 职场文书
区域销售经理岗位职责
2015/04/02 职场文书
2016大学生形势与政策心得体会
2016/01/12 职场文书
手把手教你使用TensorFlow2实现RNN
2021/07/15 Python
Tomcat执行startup.bat出现闪退的原因及解决办法
2022/04/20 Servers