Let’s take a look at the source code of this article. The add definition is as follows (omitting most of it)
add: function( elem, types, handler, data ) {
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return;
}
...
}
defines four parameters elem, types, handler and data, which are HTMLElement, event type (such as click), event response function and data respectively. In addition, types can pass multiple events separated by spaces ("mouseover mouseout"). The handler is sometimes an object (when implementing live). Data will finally be hung on the expanded event object, that is, as an attribute of the event. The event will be obtained as the first parameter in the handler, so that the data can be obtained in the handler.
Details below
if ( elem.nodeType = == 3 || elem.nodeType === 8 ) {
return;
}
Text and comment nodes are returned directly.
if ( handler === false ) {
handler = returnFalse;
} else if ( !handler ) {
// Fixes bug #7229. Fix recommended by jdalton
return;
}
The parameter handler is When false, assign handler to returnFalse, returnFalse is a function, as follows
function returnFalse() {
return false;
}
jQuery prevents the element's default behavior and stops event bubbling by setting the handler to false. This needs to be viewed in conjunction with jQuery.event.handle.
var handleObjIn, handleObj;
if ( handler. handler ) {
handleObjIn = handler;
handler = handleObjIn.handler;
}
// Make sure that the function being executed has a unique ID
if ( !handler.guid ) {
handler.guid = jQuery.guid;
}
Define variables handleObjIn, handleObj.
Handler is literally an event response (callback) function, but the presence of handler.handler here makes people feel weird. That is, when will the handler be passed in as a JS object?
Most of the time, the Function type is passed. Looking at the call of jQuery.event.add in the source code, we can find that jQuery will pass the Object type when implementing live. As follows
add: function( handleObj) {
jQuery .event.add( this,
liveConvert( handleObj.origType, handleObj.selector ),
jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
},
At this time, handleObjIn will be assigned the value of the passed JS object, but the real handler is handleObjIn.handler. This is a bit convoluted, take your time to understand it.
// Make sure that the function being executed has a unique ID
if ( !handler.guid ) {
handler.guid = jQuery.guid ;
}
The passed parameter handler adds an attribute guid, which is a number, since The increment starts from 1. Even if you use jQuery to add an event, the attribute guid will be added by default to the event response function. This guid will be used when deleting events.
// Init the element's event structure
var elemData = jQuery._data( elem );
Get elemData first, here the jQuery._data mentioned earlier is used. The first time an event is added for HTMLElement, elemData is an empty object ({}).
// If no elemData is found then we must be trying to bind to one of the
// banned noData elements
if ( !elemData ) {
return;
}
If elemData does not exist, it will be returned directly.
var events = elemData.events,
eventHandle = elemData.handle;
Define events, eventHandle. Also the first time, both variables are undefined.
if ( !events ) {
elemData.events = events = {};
}
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
return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
jQuery.event.handle.apply( eventHandle.elem, arguments ) :
undefined;
};
}
Assign values to elemData.events and elemData.handle.
// Add elem as a property of the handle function
// This is to prevent a memory leak with non-native events in IE.
eventHandle.elem = elem;
Standby elem to eventHandle, it will be deleted when event registration is deleted Set to null to avoid memory leaks in some browsers.
// Handle multiple events separated by a space
// jQuery(...).bind("mouseover mouseout", fn);
types = types.split(" ");
Convert the string with spaces as the cutter into an array. This sentence allows you to add multiple events at one time, and the handlers of multiple events are the same.
is followed by a while loop
while ( (type = types[ i ]) ) {
handleObj = handleObjIn ?
jQuery.extend({}, handleObjIn) :
{ handler: handler, data: data };
...
}
Loop the array, which is processed in sequence as follows
, get handleObj
, and process the event namespace, distinguished by a period (.). If type has a dot, it has a namespace, otherwise there is no
. Add type and guid attributes to handlerObj.
is used when deleting these subsequent events to obtain handlers and special. In most cases, addEventListener/attachEvent is used to add events. It can be seen from the variable special that special events such as ready, beforeunload and live events are specially processed. ready calls jQuery.bindReady, but jQuery.bindReady still calls addEventListener/attachEvent internally. beforeunload is added using window.onbeforeunload. Live implements event delegation, and its processing is also special.
, finally add handleObj to the array handles.
The last sentence of jQuery.event.add solves the memory leak in IE.
// Nullify elem to prevent memory leaks in IE
elem = null;
I made a picture of the data structure of jQuery event management. As follows