先用一个dome来看看on函数的使用场景:
<div id="a" style="width:100px;height:100px;background:red">
<p id="b" style="width:50px;height:50px;background:green"><span>h</span></p>
</div>
<script>
var a = $("#a");
a.on("click","p",function(e){
alert("gudalun");});
</script>
在调用on函数的时候到底发生了什么?
查看on函数的源码可以发现,它内部调用了jquery.event.add函数,on函数做了什么,实际就是这个函数做了什么?
这个函数的源码如下:
function( elem, types, handler, data, selector ) {
//以demo为例的话,这里的elem实际上是ID为#a的dom元素,types为click,handle是传进来的回调函数。
var tmp, events, t, handleObjIn,
special, eventHandle, handleObj,
handlers, type, namespaces, origType,
elemData = jQuery._data( elem );//查找这个dom中有没有缓存数据,这个结果返回了一个空的缓存对象.
if ( !elemData ) {//虽然为空但不是没有数值。
return;
}
if ( handler.handler ) {//回调函数这个对象没有handle字段,不进入这段代码 handleObjIn = handler;
handler = handleObjIn.handler;
selector = handleObjIn.selector;
}
if ( !handler.guid ) {
handler.guid = jQuery.guid++;//给这个函数初始化一个属性
}
if ( !(events = elemData.events) ) {
events = elemData.events = {};//缓存对象下初始化一个events属性和eventHandle属性。分别赋值一个空对象,和函数。这个函数就是后面绑定在这个dom元素上click事件的监听函数。
}if ( !(eventHandle = elemData.handle) ) {
eventHandle = elemData.handle = function( e ) {
return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
undefined;
};
eventHandle.elem = elem;
}
types = ( types || "" ).match( core_rnotwhite ) || [""];//给types字符匹配给定的正则,返回一个数组。这里types=[click]
t = types.length;
while ( t-- ) {
tmp = rtypenamespace.exec( types[t] ) || [];
type = origType = tmp[1];
namespaces = ( tmp[2] || "" ).split( "." ).sort();
if ( !type ) {
continue;
}
special = jQuery.event.special[ type ] || {};
type = ( selector ? special.delegateType : special.bindType ) || type;
special = jQuery.event.special[ type ] || {};
handleObj = jQuery.extend({
type: type,
origType: origType,
data: data,
handler: handler,
guid: handler.guid,
selector: selector,
needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
namespace: namespaces.join(".")
}, handleObjIn );//这里定义一个记录这个有关这个事件绑定函数信息的对象。
if ( !(handlers = events[ type ]) ) {
handlers = events[ type ] = [];//events就是前面elem.events,它是一个对象,也就是说在这个对象下,加一个type属性,初始化成一个数组。这个数组最终是用来存放DOM元素关于click事件的相关信息。在本例中是click事件,也可以是mouseover等其他时事件。
handlers.delegateCount = 0;这个数组里面有个数据delegateCount,初始化是0.
if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
if ( elem.addEventListener ) {
elem.addEventListener( type, eventHandle, false );//这里给a这个dom 添加了一个click事件,事件处理函数是上面被初始化的eventHhandle,也就是说这个a被触发了click事件后,会调用这个函数。那我们传进来的函数呢?什么时候会调用?未完待续。。。。。。
} else if ( elem.attachEvent ) {
elem.attachEvent( "on" + type, eventHandle );
}
}
}
if ( special.add ) {
special.add.call( elem, handleObj );
if ( !handleObj.handler.guid ) {
handleObj.handler.guid = handler.guid;
}
}
// Add to the element's handler list, delegates in front
if ( selector ) {
handlers.splice( handlers.delegateCount++, 0, handleObj );//
} else {
handlers.push( handleObj );
}
// Keep track of which events have ever been used, for event optimization
jQuery.event.global[ type ] = true;
}
// Nullify elem to prevent memory leaks in IE
elem = null;
},