| 上一篇:jQuery 原理的模拟代码 -2 数据部分 在 jQuery 中,实际注册的事件处理函数是一个匿名的闭包函数,这个函数最终都是通过调用 jQuery.event.handle 进行处理的。  在对象的私有扩展对象上,专门增加了一个名为 events 的事件管理对象,在这个对象上每种事件分别对应一个同名的属性,这个属性的值是一个数组,针对这个事件的处理程序依次压入这个数组中,构成一个事件处理的列表。自定义的事件处理函数即被压入这个列表中。  在事件触发的时候,通过注册的匿名函数来执行 jQuery.event.handle ,由于使用了闭包,所以在这个函数中的 this 就是事件源对象,通过这个事件源对象找到对象的私有扩展数据,然后在 events 中找到对应的事件处理程序列表,最后,依次执行。  1 /// <reference path="jQuery-core.js" /> 2 // #2076
 3
 4 // 用于生成事件处理函数的 id
 5 jQuery.guid = 1;
 6
 7 // jQuery 的事件对象
 8 jQuery.event = { // # 1555
 9
 10 // 为对象增加事件
 11 // elem 增加事件的元素, type 事件的名称, handler 事件处理程序, data 事件相关的数据
 12 add: function (elem, type, handler, data) {
 13
 14 var handleObjIn, handleObj;
 15
 16 // 确认函数有一个唯一的 ID
 17 if (!handler.guid) {
 18 handler.guid = jQuery.guid++;
 19 }
 20
 21 // 取得这个元素所对应的缓存数据对象
 22 var elemData = jQuery.data(elem);
 23
 24 // 取得元素对应的缓存对象上的事件对象和所有事件共用的处理程序
 25 var events = elemData.events = elemData.events || {};
 26 var eventHandle = elemData.handle;
 27
 28 // 是否已经有事件处理函数 handle 只有一个,都是使用 jQuery.event.handle
 29 // 通过使用闭包,使得这个函数引用当前的事件对象,参数。
 30 if (!eventHandle) {
 31 elemData.handle = eventHandle = function () {
 32 return jQuery.event.handle.apply(eventHandle.elem, arguments);
 33 };
 34 }
 35
 36 // 使得闭包处理程序可以找到事件源对象
 37 eventHandle.elem = elem;
 38
 39 //
 40 handleObj = { handler: handler, data: data};
 41 handleObj.namespace = "";
 42
 43
 44 handleObj.type = type;
 45 handleObj.guid = handler.guid;
 46
 47 // 每种事件可以有一系列的处理程序,数组形式
 48 var handlers = events[type],
 49 special = jQuery.event.special[type] || {};
 50
 51 // Init the event handler queue
 52 if (!handlers) {
 53 handlers = events[type] = [];
 54
 55 // Check for a special event handler
 56 // Only use addEventListener/attachEvent if the special
 57 // events handler returns false
 58 // 完成实际的事件注册
 59 // 实际的事件处理函数是 eventHandle
 60 if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) {
 61 // Bind the global event handler to the element
 62 if (elem.addEventListener) {
 63 elem.addEventListener(type, eventHandle, false);
 64
 65 } else if (elem.attachEvent) {
 66 elem.attachEvent("on" + type, eventHandle);
 67 }
 68 }
 69 }
 70
 71 // 自定义的处理函数在一个堆栈中,以后 jQuery.event.handle 到这里找到实际的处理程序
 72 handlers.push(handleObj);
 73
 74 // Nullify elem to prevent memory leaks in IE
 75 elem = null;
 76 },
 77
 78 global: {},
 79
 80 // 真正的事件处理函数,
 81 // 由于是通过 return jQuery.event.handle.apply(eventHandle.elem, arguments) 调用的
 82 // 所以,此时的 this 就是事件源对象,event 是事件参数
 83 handle: function (event) { // 1904
 84 var all, handlers, namespaces, namespace, events;
 85
 86 event = window.event;
 87 event.currentTarget = this;
 88
 89 // 在当前的事件对象上找到事件处理列表
 90 var events = jQuery.data(this, "events"), handlers = events[event.type];
 91
 92 if (events && handlers) {
 93 // Clone the handlers to prevent manipulation
 94 handlers = handlers.slice(0);
 95
 96 for (var j = 0, l = handlers.length; j < l; j++) {
 97 var handleObj = handlers[j];
 98
 99
 100 // 取得注册事件时保存的参数
 101 event.handler = handleObj.handler;
 102 event.data = handleObj.data;
 103 event.handleObj = handleObj;
 104
 105 var ret = handleObj.handler.apply(this, arguments);
 106 }
 107 }
 108
 109 return event.result;
 110 },
 111
 112 // #2020
 113 special: {}
 114
 115 }
 116
 117 // bind 函数定义
 118 jQuery.fn.bind = function( type, fn)
 119 {
 120 var handler = fn;
 121
 122 // 调用 jQuery.event.add 添加事件
 123 for (var i = 0, l = this.length; i < l; i++) {
 124 jQuery.event.add(this[i], type, handler);
 125 }
 126 return this;
 127 }
 128
 129 jQuery.fn.unbind = function (type, fn) {
 130 // Handle object literals
 131 if (typeof type === "object" && !type.preventDefault) {
 132 for (var key in type) {
 133 this.unbind(key, type[key]);
 134 }
 135
 136 } else {
 137 for (var i = 0, l = this.length; i < l; i++) {
 138 jQuery.event.remove(this[i], type, fn);
 139 }
 140 }
 141
 142 return this;
 143 }
 144 // click 事件的注册方法
 145 jQuery.fn.click = function (fn) {
 146 this.bind("click", fn);
 147 return this;
 148 }
 这样,对于页面上的 id 为 msg 的元素,就可以通过下面的代码注册一个 click 事件处理函数。
 1 // 事件操作 2 $("#msg").click(
 3 function () {
 4 alert(this.innerHTML);
 5 }
 6 );
 原文:http://www.cnblogs.com/haogj/archive/2010/08/02/1789759.html (编辑:宣城站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |