上一篇: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 (编辑:青岛站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|