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 相关文章推荐
JS+XML 省份和城市之间的联动实现代码
Oct 14 Javascript
Jquery异步请求数据实例代码
Dec 28 Javascript
jquery复选框checkbox实现删除前判断
Apr 20 Javascript
js给selected添加options的方法
May 06 Javascript
js基于面向对象实现网页TAB选项卡菜单效果代码
Sep 09 Javascript
基于jQuery实现仿QQ空间送礼物功能代码
May 24 Javascript
全面解析Bootstrap中tab(选项卡)的使用方法
Jun 06 Javascript
如何解决手机浏览器页面点击不跳转浏览器双击放大网页
Jul 01 Javascript
JS中把函数作为另一函数的参数传递方法(总结)
Jun 28 Javascript
JavaScript编程设计模式之构造器模式实例分析
Oct 25 Javascript
JS实现导出Excel的五种方法详解【附源码下载】
Mar 15 Javascript
浅谈JS对象添加getter与setter的5种方法
Jun 09 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
怎样在UNIX系统下安装MySQL
2006/10/09 PHP
php中的一些数组排序方法分享
2012/07/20 PHP
用来解析.htpasswd文件的PHP类
2012/09/05 PHP
PHP判断远程图片是否存在的几种方法
2014/05/04 PHP
php连接oracle数据库的核心步骤
2016/05/26 PHP
PHP延迟静态绑定使用方法实例解析
2020/09/05 PHP
实用的Jquery选项卡TAB示例代码
2013/08/28 Javascript
Lua表达式和控制结构学习笔记
2014/12/15 Javascript
JavaScript里四舍五入函数round用法实例
2015/04/06 Javascript
js淡入淡出焦点图幻灯片效果代码分享
2015/09/08 Javascript
js实现字符串和数组之间相互转换操作
2016/01/12 Javascript
AngularJS入门教程之服务(Service)
2016/07/27 Javascript
详解bootstrap的modal-remote两种加载方式【强化】
2017/01/27 Javascript
ES6生成器用法实例分析
2017/04/10 Javascript
详谈angularjs中路由页面强制更新的问题
2017/04/24 Javascript
react路由配置方式详解
2017/08/07 Javascript
详解tween.js的使用教程
2017/09/14 Javascript
实例解析ES6 Proxy使用场景介绍
2018/01/08 Javascript
vue 组件之间事件触发($emit)与event Bus($on)的用法说明
2020/07/28 Javascript
js仿京东放大镜效果
2020/08/09 Javascript
[02:17]《辉夜杯》TRG战队巡礼
2015/10/26 DOTA
[57:24]LGD vs VGJ.T 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python创建日历实例
2014/08/21 Python
python创建列表和向列表添加元素的实现方法
2017/12/25 Python
python将字符串以utf-8格式保存在txt文件中的方法
2018/10/30 Python
详解用python实现基本的学生管理系统(文件存储版)(python3)
2019/04/25 Python
python通过http下载文件的方法详解
2019/07/26 Python
Python3.6+selenium2.53.6自动化测试_读取excel文件的方法
2019/09/06 Python
Python 在 VSCode 中使用 IPython Kernel 的方法详解
2020/09/05 Python
让IE6、IE7、IE8支持CSS3的脚本
2010/07/20 HTML / CSS
HTML5之WebGL 3D概述(下)—借助类库开发及框架介绍
2013/01/31 HTML / CSS
预订全球最佳旅行体验:Viator
2018/03/30 全球购物
德国旅游网站:weg.de
2018/06/03 全球购物
衰败城市英国官网:Urban Decay英国
2020/04/29 全球购物
广告学毕业生求职信
2014/01/30 职场文书
社区文明创建工作总结2015
2015/04/21 职场文书