JQuery1.9.1 bind event to the source code analysis series (10) Event System _ jquery

Source: Internet
Author: User
This article mainly introduces the jQuery1.9.1 source code analysis series (10) Event System-related information about event binding. You can refer to the following methods for event binding, the binding method (elem. click = function (){...})) I don't really want to recommend it to anyone. The main reason is that elem. click = fn can only be bound to one event for processing. Only the last binding result will be retained for multiple bindings.

The following describes how to bind events to jquery.

The Code is as follows:


JQuery. fn. eventType ([data,] fn])

For example, eventType indicates the event type, such as click: $ ("# chua"). click (fn );

Data is generally not used. In this way, events are bound to ("# chua") without delegate events, which is closer to js native event binding. Let's take a look at the source code

JQuery. each ("blur focus focusin focusout load resize scroll unload click dblclick" + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave" + "change select submit keydown keypress keyup error contextmenu "). split (""), function (I, name) {// merge 15 events and add them to jQuery. on fn, internal call this. on/this. trigger jQuery. fn [name] = function (data, fn) {return arguments. length> 0? This. on (name, null, data, fn): // if no parameter is specified, the specified event this is triggered immediately. trigger (name) ;};}); jQuery. fn. bind (types [, data], fn)

For example, $ ("# chua"). bind ("click", fn ). Directly bind the event to $ ("# chua") without entrusting the event. Source code

bind: function( types, data, fn ) { return this.on( types, null, data, fn );},unbind: function( types, fn ) { return this.off( types, null, fn );} jQuery.fn.delegate(selector, types[, data], fn)

As the name suggests, the delegate function is used for event delegation. It delegates the Response Processing corresponding to the selector to the elements matching the current jQuery.

For example: $ (document). delegate ('# big', "click", dohander); analyze the event delegate processing process here by the way.

When you click the "# big" element, the event click will bubble up until the document node;

The document is bound to the processing event, which will be called to the event distributor dispatch;

In dispatch, extract the handlers list of all delegate events of the corresponding event type click;

Event source event.tar get filters out the delegate event in the delegate event list handlers. The Node corresponding to the selector attribute of each element is in the delegate event between the event source and the delegate node document (including the event source) and saves it as handlerQueue;

Execute event processing in handlerQueue.

The above is a rough process and will be analyzed in detail later. First look at the delegate source code

delegate: function( selector, types, data, fn ) { return this.on( types, selector, data, fn );},undelegate: function( selector, types, fn ) { // ( namespace ) or ( selector, types [, fn] ) return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );}jQuery.fn.one( types[, selector[, data]], fn )

The event processing functions bound by one () function are all one-time. Only when an event is triggered for the first time will this event processing function be executed. After the event is triggered, jQuery removes the binding of the current event.

For example, $ ("# chua"). one ("click", fn); binds a one-time click event to the # chua node.

$ (Document). one ("click", "# chua", fn); delegates the click event of # chua to the document for processing. Source code

one: function( types, selector, data, fn ) {  return this.on( types, selector, data, fn, 1 );} jQuery.fn.trigger(type[, data])jQuery.fn.triggerHandler(type[, data])

Trigger triggers a type event for each element matched by the jQuery object. For example, $ ("# chua"). trigger ("click ");

TriggeHandler only triggers type events corresponding to the first element of the element matched by the jQuery object, and does not trigger the default action of the event.

// Trigger: function (type, data) {return this. each (function () {jQuery. event. trigger (type, data, this) ;}}, // trigger the specified type event of the first element in the jQuery object immediately without triggering the event (such as form submission) triggerHandler: function (type, data) {var elem = this [0]; if (elem) {return jQuery. event. trigger (type, data, elem, true );}}

After analyzing some event bindings, have you found that they are all bound using the. on method? This is also why we advocate the unified use of on binding (except for the one method ).

jQuery.fn.on( types[, selector[, data]], fn )

Half of the code bound to the. on event actually processes the processing of passing different parameters, which is also the price of jQuery's "Write less". do more. Finally, jQuery. event. add is used to bind events.

 There are several key points for binding events to jQuery. event. add:

First, use the internal cache to save node elem event information

// Obtain the cached data elemData = jQuery. _ data (elem);... // set the cached data if (! (Events = elemData. events) {events = elemData. events ={};} if (! (EventHandle = elemData. handle) {eventHandle = elemData. handle = function (e ){...}; // use elem as a feature of the handle function to prevent memory leakage caused by non-local ie events. eventHandle. elem = elem ;}

Second, set the binding event information, especially the specified selector, Response Processing handler, RESPONSE event type, namespace

// HandleObj: Set the binding event information. Throughout event processing handleObj = jQuery. extend ({type: type, origType: origType, data: data, handler: handler, guid: handler. guid, selector: selector, // For use in libraries implementing. is (). we use this for POS matching in 'select' // "needsContext": new RegExp ("^" + whitespace + "* [> + ~] | :( Even | odd | eq | gt | lt | nth | first | last )(? : \ ("+ // Whitespace + "*((? :-\ D )? \ D *) "+ whitespace +" * \) | )(? = [^-] | $) "," I ") // used to determine the intimacy needsContext: selector & jQuery. expr. match. needsContext. test (selector), namespace: namespaces. join (". ")}, handleObjIn );

Third, in the event list of the node, the real delegated event list is placed in front, and is synchronized with the delegateCount attribute, that is, events. click. length is assumed to be 3, events. click. delegateCount is assumed to be 2. The events specified by events. click [0] and events. click [1] are delegate events. The event corresponding to the third events. click [2] is not a delegate event, but a node event.

// Add the event object handleObj to the processing list of the element, place the delegate event in front, and the delegate proxy count increases progressively if (selector) {handlers. splice (handlers. delegateCount ++, 0, handleObj);} else {handlers. push (handleObj );}

The source code and the structure after adding events have been analyzed in the previous chapter. For details, click to view

The binding has a public function jQuery. fn. on. Unbinding also has a public function jQuery. fn. off

jQuery.fn.off([ types[, selector][, fn]] )

The parameter passing here has a special case: When types is a browser event object, it means to remove (unbind) The delegate event specified by event. selector on the delegate Node

// The input parameter is an event and bound to the processing function if (types & types. preventDefault & types. handleObj) {// (event) dispatched jQuery. event handleObj = types. handleObj; // types. delegateTarget is the event-hosted object jQuery (types. delegateTarget ). off (// combines the type handleObj recognized by jQuery. namespace? HandleObj. origType + "." + handleObj. namespace: handleObj. origType, handleObj. selector, handleObj. handler); return this ;}

In any case, the jQuery. event. remove function is called to unbind events.

  The complete source code of jQuery. fn. off is as follows:

Off: function (types, selector, fn) {var handleObj, type; // The input parameter is an event and bound to the processing function if (types & types. preventDefault & types. handleObj) {// (event) dispatched jQuery. event handleObj = types. handleObj; // types. delegateTarget is the event-hosted object jQuery (types. delegateTarget ). off (// combines the type handleObj recognized by jQuery. namespace? HandleObj. origType + ". "+ handleObj. namespace: handleObj. origType, handleObj. selector, handleObj. handler); return this;} if (typeof types = "object") {// (types-object [, selector]) for (type in types) {this. off (type, selector, types [type]);} return this;} if (selector = false | typeof selector = "function ") {// (types [, fn]) fn = selector; selector = undefined;} if (fn = false) {fn = returnFalse;} return this. each (function () {jQuery. event. remove (this, types, fn, selector );});}

  Next, we will analyze the low-level api jQuery. event. remove that is unbound from the event.

JQuery. event. remove

When jQuery uses the. off () function to bind an event, the basic function called internally is jQuery. event. remove. The process of this function is as follows:

1. Break down the imported event type types to be deleted, and traverse the type. If there is no event name for the event to be deleted, only the namespace will delete all bound events under the namespace.

// Break down types to type. the namespace is the array types = (types | "") of the unit element ""). match (core_rnotwhite) | [""]; t = types. length; while (t --) {tmp = rtypenamespace.exe c (types [t]) | []; type = origType = tmp [1]; namespaces = (tmp [2] | ""). split (". "). sort (); // unbind all the event if (! Type) {for (type in events) {jQuery. event. remove (elem, type + types [t], handler, selector, true) ;}continue ;}...

2. During the traversal type process, the matching events are deleted and the proxy count is corrected.

Type = (selector? Special. delegateType: special. bindType) | type; handlers = events [type] | []; tmp = tmp [2] & new RegExp ("(^ | \\.) "+ namespaces. join ("\\. (? :. *\\. |) ") + "(\\. | $) "); // Delete the matching event origCount = j = handlers. length; while (j --) {handleObj = handlers [j]; // you can remove if (mappedTypes | origType = handleObj. origType )&&(! Handler | handler. guid === handleObj. guid )&&(! Tmp | tmp. test (handleObj. namespace ))&&(! Selector | selector === handleObj. selector | selector = "**" & handleObj. selector) {handlers. splice (j, 1); if (handleObj. selector) {handlers. delegateCount --;} if (special. remove) {special. remove. call (elem, handleObj );}}}

3. If the event processor of the specified type on the node is empty, the event processing object of this type on events will be removed.

// Remove the event processing object // (avoid infinite recursion during the process of removing special events. The next chapter will detail this situation) if (origCount &&! Handlers. length) {// For example var js_obj = document. createElement ("p"); js_obj.onclick = function (){...} // The above js_obj is a reference of a DOM element. The DOM element remains in the web page for a long time and will not disappear. The onclick attribute of this DOM element, it is also an internal function reference (closure), and this anonymous function has a hidden Association (scope chain) with js_obj, so it forms a circular reference. if (! Special. teardown | special. teardown. call (elem, namespaces, elemData. handle) === false) {jQuery. removeEvent (elem, type, elemData. handle);} delete events [type];}

4. If no bound events exist on the node, clear the event processing entry handle.

If (jQuery. isEmptyObject (events) {delete elemData. handle; // removeData also checks whether the event object is empty, so it is used to replace delete jQuery. _ removeData (elem, "events ");}

Extended: delete jQuery. removeEvent from browser events

JQuery. removeEvent = document. removeEventListener? Function (elem, type, handle) {if (elem. removeEventListener) {elem. removeEventListener (type, handle, false) ;}}: function (elem, type, handle) {var name = "on" + type; if (elem. detachEvent) {// #8545, #7054, to avoid Memory leakage of custom events in the IE6-8 // detachEvent needs to pass the first parameter, it cannot be an undefined if (typeof elem [name] === core_strundefined) {elem [name] = null;} elem. detachEvent (name, handle );}};

The above content is the binding event of the jQuery 1.9.1 source code analysis series (10) Event System introduced by xiaobian. I hope you will like it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.