/* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. */ jQuery.event = {
// Caller can pass in an object of custom data in lieu of the handler // 这里在之前一直不明白为什么要这么做,原因就是这里的handler 可以是一个function,即我们平时所说的绑定的事件方法 // 同时也可以是一个事件对象,也就是下面所说的handleObj,那么如果是在jQuery的内部是可以传递一个事件对象过来的 if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; selector = handleObjIn.selector; }
// Make sure that the handler has a unique ID, used to find/remove it later // 这里分配guid if ( !handler.guid ) { handler.guid = jQuery.guid++; }
// Init the element's event structure and main handler, if this is the first // 从缓存系统中,从缓存事件对象中获取events数组 events = elemData.events; if ( !events ) { elemData.events = events = {}; } //主监听函数,唯一一个绑定到dom元素的方法,会调用dispatch分配事件 eventHandle = elemData.handle; if ( !eventHandle ) { elemData.handle = eventHandle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded //这里主要防止trigger 手动触发时的二次冒泡。这里在trigger中,会存在模拟冒泡的事件, //主要针对不能冒泡的事件如:focus 就只能模拟冒泡事件 //如果已经冒泡过了,那么在这里就不需要再次执行了。 returntypeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : undefined; }; // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events // 这里主要针对ie的内存问题 eventHandle.elem = elem; }
// Handle multiple events separated by a space // jQuery(...).bind("mouseover mouseout", fn); // 切割多个事件组合 types = jQuery.trim( hoverHack(types) ).split( " " ); for ( t = 0; t < types.length; t++ ) { //使用正则切割命名空间 // rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, // 如: click.namespace ,hover.namespace // ==> ["click.namespace", "click", "namespace", index: 0, input: "click.namespace"] tns = rtypenamespace.exec( types[t] ) || []; type = tns[1]; namespaces = ( tns[2] || "" ).split( "." ).sort();
// If event changes its type, use the special event handlers for the changed type // 这里主要对事件进行修复,看是否在special中存有定义,如果有,刚使用special中的事件类型替换之 // 主要是某些原生事件,对浏览器存在兼容问题,所以需要替换 special = jQuery.event.special[ type ] || {};
// If selector defined, determine special event api type, otherwise given type // 这里的selector为代理事件,如果存在selector,那么就存在冒泡事件 // 对于delegateType主要是对原生不能冒泡的事件进行替换如:focus => focusin // 那么如果原生事件对于冒泡没有问题,那么检测绑定类型是否需要修复:如: mouseover ==> mouseenter type = ( selector ? special.delegateType : special.bindType ) || type;
// Update special based on newly reset type special = jQuery.event.special[ type ] || {};
// Init the event handler queue if we're the first handlers = events[ type ]; if ( !handlers ) { handlers = events[ type ] = []; handlers.delegateCount = 0;
// Only use addEventListener/attachEvent if the special events handler returns false 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 );