jQuery的实现原理的模拟代码 -3 事件处理
jQuery的实现原理的模拟代码 -3 事件处理
发布时间:2016-12-30 来源:查字典编辑
摘要:在对象的私有扩展对象上,专门增加了一个名为events的事件管理对象,在这个对象上每种事件分别对应一个同名的属性,这个属性的值是一个数组,针...

在对象的私有扩展对象上,专门增加了一个名为 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教程学习
编程开发子分类