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 相关文章推荐
javascript 短路法代码精简
Aug 20 Javascript
javascript小数四舍五入多种方法实现
Dec 23 Javascript
处理文本部分内容的TextRange对象应用实例
Jul 29 Javascript
15个常用的jquery代码片段
Dec 19 Javascript
分享jQuery插件的学习笔记
Jan 14 Javascript
js点击文本框弹出可选择的checkbox复选框
Feb 03 Javascript
jQuery实现圣诞节礼物传送(花式轮播)
Dec 25 Javascript
用vue写一个仿简书的轮播图的示例代码
Mar 13 Javascript
vue中axios的封装问题(简易版拦截,get,post)
Jun 15 Javascript
javascript实现考勤日历功能
Nov 29 Javascript
vue Treeselect 树形下拉框:获取选中节点的ids和lables操作
Aug 15 Javascript
javascript中layim之查找好友查找群组
Feb 06 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
PHP5中MVC结构学习
2006/10/09 PHP
laravel 解决crontab不执行的问题
2019/10/22 PHP
jquery 得到当前页面高度和宽度的两个函数
2010/02/21 Javascript
js里的prototype使用示例
2010/11/19 Javascript
javascript 用函数语句和表达式定义函数的区别详解
2014/01/06 Javascript
js获取浏览器基本信息大全
2014/11/27 Javascript
JavaScript 动态加载脚本和样式的方法
2015/04/13 Javascript
JS Attribute属性操作详解
2016/05/19 Javascript
js注入 黑客之路必备!
2016/09/14 Javascript
require、backbone等重构手机图片查看器
2016/11/17 Javascript
jQuery实用密码强度检测
2017/03/02 Javascript
微信小程序 登录的简单实现
2017/04/19 Javascript
利用Javascript开发一个二维周视图日历
2017/12/14 Javascript
javascript设计模式 ? 中介者模式原理与用法实例分析
2020/04/20 Javascript
[06:57]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD 选手采访
2021/03/11 DOTA
python绘制热力图heatmap
2020/03/23 Python
Python文件打开方式实例详解【a、a+、r+、w+区别】
2019/03/30 Python
Python 中Django验证码功能的实现代码
2019/06/20 Python
Python3进制之间的转换代码实例
2019/08/24 Python
pygame实现俄罗斯方块游戏(基础篇2)
2019/10/29 Python
python中删除某个元素的方法解析
2019/11/05 Python
为什么称python为胶水语言
2020/06/16 Python
13个Pandas实用技巧,助你提高开发效率
2020/08/19 Python
Django中日期时间型字段进行年月日时分秒分组统计
2020/11/27 Python
HTML5对手机页面长按会粘贴复制禁用的解决方法
2016/07/19 HTML / CSS
维氏瑞士军刀英国网站:Victorinox英国
2019/07/04 全球购物
一套英文Java笔试题面试题
2016/04/21 面试题
工程师岗位职责
2013/11/08 职场文书
有多年工作经验的自我评价
2014/03/02 职场文书
公司年会策划方案
2014/05/17 职场文书
先进工作者申报材料
2014/12/23 职场文书
求职简历自我评价范文
2015/03/10 职场文书
走进毛泽东观后感
2015/06/04 职场文书
秋收起义观后感
2015/06/11 职场文书
mysql优化之query_cache_limit参数说明
2021/07/01 MySQL
图神经网络GNN算法
2022/05/11 Python