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 学习之二 属性 文本与值(text,val)
Nov 25 Javascript
PageSwitch插件实现100种不同图片切换效果
Jul 28 Javascript
jquery实现经典的淡入淡出选项卡效果代码
Sep 22 Javascript
JS实现对中文字符串进行utf-8的Base64编码的方法(使其与Java编码相同)
Jun 21 Javascript
Angular2使用Angular CLI快速搭建工程(一)
May 21 Javascript
微信小程序封装http访问网络库实例代码
May 24 Javascript
BootStrap selectpicker后台动态绑定数据的方法
Jul 28 Javascript
使用百度地图实现地图网格的示例
Feb 06 Javascript
Vue 列表上下过渡效果的实例代码
Jun 25 Javascript
微信小程序 冒泡事件原理解析
Sep 27 Javascript
Vue 中 filter 与 computed 的区别与用法解析
Nov 21 Javascript
小程序简单两栏瀑布流效果的实现
Dec 18 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下获取客户端ip地址的函数
2010/03/15 PHP
php实现文件下载功能的几个代码分享
2014/05/10 PHP
PHP、Nginx、Apache中禁止网页被iframe引用的方法
2020/10/01 PHP
php实现当前页面点击下载文件的简单方法
2016/09/22 PHP
php写入mysql中文乱码的实例解决方法
2019/09/17 PHP
如何在PHP中使用AES加密算法加密数据
2020/06/24 PHP
javascript之通用简单的table选项卡实现(二)
2010/05/09 Javascript
原生JS操作网页给p元素添加onclick事件及表格隔行变色
2013/12/01 Javascript
jQuery实现的动态伸缩导航菜单实例
2015/05/07 Javascript
JavaScript调用客户端Java程序的方法
2015/07/27 Javascript
javascript如何实现360度全景照片问题汇总
2016/04/04 Javascript
jquery实现文本框的禁用和启用
2016/12/07 Javascript
React中ES5与ES6写法的区别总结
2017/04/21 Javascript
微信小程序 新建登录页并实现tabBar隐藏
2017/06/13 Javascript
基于node.js的fs核心模块读写文件操作(实例讲解)
2017/09/10 Javascript
微信小程序 POST请求的实例详解
2017/09/29 Javascript
基于Vue实现图书管理功能
2017/10/17 Javascript
jQuery中将json数据显示到页面表格的方法
2018/05/27 jQuery
一篇文章带你搞懂Vue虚拟Dom与diff算法
2020/08/25 Javascript
详解python调度框架APScheduler使用
2017/03/28 Python
wxPython之解决闪烁的问题
2018/01/15 Python
Sanic框架配置操作分析
2018/07/17 Python
python:批量统计xml中各类目标的数量案例
2020/03/10 Python
python如何使用代码运行助手
2020/07/03 Python
PyTorch中的拷贝与就地操作详解
2020/12/09 Python
纯CSS3打造属于自己的“小黄人”
2016/03/14 HTML / CSS
HTML5视频播放插件 video.js介绍
2018/09/29 HTML / CSS
Probikekit日本:自行车套件,跑步和铁人三项装备
2017/04/03 全球购物
韩国江南富人区高端时尚百货商场:Galleria(格乐丽雅)
2018/03/27 全球购物
学年自我鉴定范文
2013/10/01 职场文书
数控技术专科生自我评价
2014/01/08 职场文书
房屋鉴定委托书范本
2014/09/23 职场文书
领导班子群众路线与四风问题对照检查材料思想汇报
2014/10/11 职场文书
党的群众路线教育实践活动党员个人整改措施
2014/10/27 职场文书
信访维稳工作汇报
2014/10/27 职场文书
结婚纪念日感言
2015/08/01 职场文书