研究一下jQuery的事件模型。
1.定义
jQuery.event={
add:function(){},
remove:function(){},
triggle:function(){},
handle:function(){},
fix:function(){},
global:{},
props:"XXX YYY zzz".split(" "),
guid:IE8,
proxy:jQuery.proxy,
special:{
ready: {
setup:jQuery.bindReady,
teardown: jQuery.noop
},
live:{
add:function(){},
remove:function(){}
},
beforeunload:{
setup:function(){},
teardown:function(){}
}
}
}
jQuery.event为一个固有对象,其里面包含各种静态工具方法。用户调用bind unbind one等等函数时,其内部实现必然会调用这些工具方法。
该对象还有一些属性后文介绍。现在按照普通的用法看看事件机制是如何构成的。
2.bind 的解析过程
当我们写
$("p").bind("click", function(e){})
jQuery引擎到底做了什么事情?
首先,选择器选择到了一个jQuery对象(其实就是DOM对象外加一些其他jQuery放进去的属性),在该对象上调用bind方法。
jQuery对象上的方法,不同于jQuery那个函数对象里面的方法,就如在上一篇文章《工具方法》中所说的,jQuery对象的方法必需都要在原型里面注册过才行。
看bind方法什么时候加入到jQuery.prototype里面去的。搜索“bind: function”企图看bind方法的定义,只找到unbind的定义。原来bind 和 one在上面一个语句块里面一起定义的。
jQuery.each(["bind", "one"], function( i, name ) {
jQuery.fn[ name ] = function( type, data, fn ) {
STATEMENTS;
return this;
};
});
看到jQuery.fn就明白了。由上一篇文章所述,jQuery.fn已经与jQuery的原型关联起来了,往fn里面放任何方法都同时被prototype拥有。
现在可知,此处注册了2个方法bind 和one 。 最后return this 依然是为了链式操作。
看STATEMENTS;函数体里面到底作了什么。
jQuery.fn[ name ] = function( type, data, fn ) {
// Handle object literals
if ( typeof type === "object" ) { //一般情况下是 typeof type = "string"
for ( var key in type ) {
this[ name ](key, data, type[key], fn);
}
return this;
}
if ( jQuery.isFunction( data ) || data === false ) {
fn = data;
data = undefined;
}
var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
jQuery( this ).unbind( event, handler );
return fn.apply( this, arguments );
}) : fn;
if ( type === "unload" && name !== "one" ) {
this.one( type, data, fn );
} else {
for ( var i = 0, l = this.length; i < l; i++ ) {
jQuery.event.add( this[i], type, handler, data );
}
}
return this;
};
由bind的用法我们知道,该bind方法接受2个参数 “click” 和 function(e){} 也就是 type(事件类型) 和fn(回调函数)。
如果是one来绑定事件,另说。
如果是bind来作,则主要操作在最后一个else里面。
this.length是什么?我们在《工具方法》一章说过,jQuery对象是类数组,有key为0,1,2,3...的属性值,还有一个名为length的属性值,指示的就是前面的数数。
length就是该jQuery对象包含的Element元素的个数。也就是说对每一个Element元素调用一个add的方法。
jQuery.event.add( this[i], type, handler, data );
jQuery.event.add()是一个静态工具方法。不用看代码就可以猜到大致作用:在this[i]指示的Element元素上监听名字为type的事件类型,其回调函数为handler。data另看。
其关键代码如下:
add: function( elem, types, handler, data ) {
//处理ie兼容性;
//唯一guid
//这个方法取到elem 的私有数据expando。看来所有事件处理的东西都放在对象的私有属性expando上了。
//每个elem对象有一个属性,名与"jQueryXXXX"类似,是自动生成的,(在运行期,所有elem对象的这个属性名都一样为jQuery.expando)
//这个属性的值,是一个唯一的自增的id,它对应一个全局数组对象jQuery.cache的一个条目,那个条目值,也是一个对象,即为该elem
//对象的私有数据保存的地方。
var elemData = jQuery.data( elem );
var events = elemDate['event'] // events是一个对象。
var eventHandle = elemData.handle //eventHandle是一个方法。
eventHandle.elem = elem;
handleObj = {
handler : handler;
data : data
}
handleObj.type = tpe;
//把handleObj 塞到 handlers里头。 handlers是events的一个属性type的值。
}
事件及其处理函数被当作Elemen元素的私有数据,维护在cache里面了。

上图是追踪jQuery对象里面Element对象,绑定事件的图示。其中第二列中4个不应该是jQuery对象,应该是Element对象才对。
1.定义
jQuery.event={
add:function(){},
remove:function(){},
triggle:function(){},
handle:function(){},
fix:function(){},
global:{},
props:"XXX YYY zzz".split(" "),
guid:IE8,
proxy:jQuery.proxy,
special:{
ready: {
setup:jQuery.bindReady,
teardown: jQuery.noop
},
live:{
add:function(){},
remove:function(){}
},
beforeunload:{
setup:function(){},
teardown:function(){}
}
}
}
jQuery.event为一个固有对象,其里面包含各种静态工具方法。用户调用bind unbind one等等函数时,其内部实现必然会调用这些工具方法。
该对象还有一些属性后文介绍。现在按照普通的用法看看事件机制是如何构成的。
2.bind 的解析过程
当我们写
$("p").bind("click", function(e){})
jQuery引擎到底做了什么事情?
首先,选择器选择到了一个jQuery对象(其实就是DOM对象外加一些其他jQuery放进去的属性),在该对象上调用bind方法。
jQuery对象上的方法,不同于jQuery那个函数对象里面的方法,就如在上一篇文章《工具方法》中所说的,jQuery对象的方法必需都要在原型里面注册过才行。
看bind方法什么时候加入到jQuery.prototype里面去的。搜索“bind: function”企图看bind方法的定义,只找到unbind的定义。原来bind 和 one在上面一个语句块里面一起定义的。
jQuery.each(["bind", "one"], function( i, name ) {
jQuery.fn[ name ] = function( type, data, fn ) {
STATEMENTS;
return this;
};
});
看到jQuery.fn就明白了。由上一篇文章所述,jQuery.fn已经与jQuery的原型关联起来了,往fn里面放任何方法都同时被prototype拥有。
现在可知,此处注册了2个方法bind 和one 。 最后return this 依然是为了链式操作。
看STATEMENTS;函数体里面到底作了什么。
jQuery.fn[ name ] = function( type, data, fn ) {
// Handle object literals
if ( typeof type === "object" ) { //一般情况下是 typeof type = "string"
for ( var key in type ) {
this[ name ](key, data, type[key], fn);
}
return this;
}
if ( jQuery.isFunction( data ) || data === false ) {
fn = data;
data = undefined;
}
var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
jQuery( this ).unbind( event, handler );
return fn.apply( this, arguments );
}) : fn;
if ( type === "unload" && name !== "one" ) {
this.one( type, data, fn );
} else {
for ( var i = 0, l = this.length; i < l; i++ ) {
jQuery.event.add( this[i], type, handler, data );
}
}
return this;
};
由bind的用法我们知道,该bind方法接受2个参数 “click” 和 function(e){} 也就是 type(事件类型) 和fn(回调函数)。
如果是one来绑定事件,另说。
如果是bind来作,则主要操作在最后一个else里面。
this.length是什么?我们在《工具方法》一章说过,jQuery对象是类数组,有key为0,1,2,3...的属性值,还有一个名为length的属性值,指示的就是前面的数数。
length就是该jQuery对象包含的Element元素的个数。也就是说对每一个Element元素调用一个add的方法。
jQuery.event.add( this[i], type, handler, data );
jQuery.event.add()是一个静态工具方法。不用看代码就可以猜到大致作用:在this[i]指示的Element元素上监听名字为type的事件类型,其回调函数为handler。data另看。
其关键代码如下:
add: function( elem, types, handler, data ) {
//处理ie兼容性;
//唯一guid
//这个方法取到elem 的私有数据expando。看来所有事件处理的东西都放在对象的私有属性expando上了。
//每个elem对象有一个属性,名与"jQueryXXXX"类似,是自动生成的,(在运行期,所有elem对象的这个属性名都一样为jQuery.expando)
//这个属性的值,是一个唯一的自增的id,它对应一个全局数组对象jQuery.cache的一个条目,那个条目值,也是一个对象,即为该elem
//对象的私有数据保存的地方。
var elemData = jQuery.data( elem );
var events = elemDate['event'] // events是一个对象。
var eventHandle = elemData.handle //eventHandle是一个方法。
eventHandle.elem = elem;
handleObj = {
handler : handler;
data : data
}
handleObj.type = tpe;
//把handleObj 塞到 handlers里头。 handlers是events的一个属性type的值。
}
事件及其处理函数被当作Elemen元素的私有数据,维护在cache里面了。

上图是追踪jQuery对象里面Element对象,绑定事件的图示。其中第二列中4个不应该是jQuery对象,应该是Element对象才对。