JQuery 1.9.1 Source Analysis Series (10) Event System binding event _jquery

Source: Internet
Author: User

There are many ways to bind events, using jquery as a way of binding (Elem.click = function () {...}) I don't really want to recommend it to everyone. The main reason is that ELEM.CLICK=FN can only bind to one event processing, and multiple bindings will only hold the result of the last binding.

Here are some ways to introduce the jquery binding event.

Copy Code code as follows:

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

For example, EventType refers to the type of event, such as click: $ ("#chua"). Click (FN);

Data This parameter is generally not used. This way events are bound to ("#chua") without delegate events, and JS native event bindings are closer. Let's take a look at the source

Jquery.each (Blur focus focusin focusout Load resize scroll unload click DblClick "+
  " MouseDown MouseUp mousemove m Ouseover mouseout mouseenter mouseleave "+
  " Change Select Submit KeyDown keypress error KeyUp "). Split (" " ), function (i, name) {
//merge 15 kinds of events to Jquery.fn, internal call This.on/this.trigger
jquery.fn[name] = funct      Ion (data, FN) {return
arguments.length > 0?
This.on (name, NULL, data, FN):
//If the specified event
This.trigger (name) is immediately triggered without parameters;
 };
});
JQuery.fn.bind (types[, data], FN)

such as $ ("#chua"). Bind ("click", fn). The event is bound directly to $ ("#chua") without a delegate event. Source

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 implies delegate this function is used to do event delegates, the selector selector corresponding response processing is delegated to the elements that are matched by the current jquery.

For example: $ (document). Delegate (' #big ', "click", Dohander); analyze here and analyze the process of the event delegate.

When you click on the "#big" element, the event click Bubbles until the document node.

Document binds the handling event, which is invoked to the event dispatcher dispatch;

Dispatch all the delegate events list handlers the corresponding event type click;

According to the event source Event.target filter out the selector attribute of each element in the delegate event list handlers the node that corresponds to the delegate event between the event original and the delegate node document (including the event source) is saved as a handlerqueue;

Perform the event handling within the Handlerqueue.

The above is a rough process, followed by a detailed analysis. First look at the delegate source

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? t His.off (Selector, "* *"): This.off (types, selector | | "* *", FN);
}
JQuery.fn.one (types[, selector[, data]], FN)

Event-handling functions that are bound by one () function are one-time, and are executed only when the event is first triggered. Once triggered, jquery removes the current event binding.

such as $ ("#chua"). One ("click", fn); bind a one-time click event for the #chua node

$ (document). One ("click", "#chua", FN); delegate the #chua click event to document processing. Source

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 the type of event for each element corresponding to the jquery object. such as $ ("#chua"). Trigger ("click");

Triggehandler triggers only events of type type for the first element in the element that matches the jquery object, and does not trigger the default behavior of the event.

Immediately triggers the event
trigger:function (type, data) {return
 This.each (function () {
  ) of all elements within the jquery object of the specified type. JQuery.event.trigger (type, data, this);}
 ;
///immediately triggers the event of the specified type of the first element within the jquery object and does not trigger the default behavior of the event (such as form submission)
triggerhandler:function (type, data) {
 var elem = this[0];
 if (elem) {return
  JQuery.event.trigger (type, data, Elem, True);
 }

The above analysis of some of the event binding, there is no find that they are using the. On mode of binding? This is why it is the reason to advocate for unified use on to bind (except one).

JQuery.fn.on (types[, selector[, data]], FN)

A. On event binding half of the code is actually handling the handling of passing different parameters, which is also the cost of jquery's slogan write less. Finally, the jQuery.event.add is used to bind the event.

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

First, use internal caching to save event information for node Elem

Gets the cached data 
Elemdata = Jquery._data (elem);
...
Sets 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 leaks caused by IE non-local events
    eventhandle.elem = Elem;
   }

The second is to set the binding event information, especially the specified selector selector, response processing handler, response event type type, namespace namespace

 Handleobj: Sets the binding event information. Throughout the event handling
  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 as POS matching in ' select '
   //' Needscontext ': New RegExp ("^" + whitespace + "*[>+~]|:( Even|odd|eq|gt|lt|nth|first|last) (?: \ \ ("+
   //whitespace +" * (?:-\ \d) \\d*) "+ whitespace +" *\\) |) (? =[^-]|$) "," I ")
   //used to judge intimate relationships
   Needscontext:selector && jQuery.expr.match.needsContext.test ( selector),
   namespace:namespaces.join (".")
  }, Handleobjin);

Third, in the node's list of events, the real delegate event list is placed in front, and the Delegatecount attribute is synchronized, that is, the events.click.length assumption is that the 3,events.click.delegatecount is assumed to be 2. The events specified by events.click[0] and events.click[1] are delegate events. The third events.click[2] corresponds to an event that is not a delegate event, but an event of the node itself.

 Adds the event object handleobj to the processing list of the elements, the delegate event is placed ahead, and the delegate-agent count increments
  if (selector) {
   handlers.splice (handlers.delegatecount++, 0, handleobj);
  } else {
   Handlers.push (handleobj);
  }

Source code and after adding the structure of the event has been analyzed, please click to view the details

Binding has a common function jQuery.fn.on. Uncoupling also has a common function jQuery.fn.off

JQuery.fn.off ([types[, selector][, FN]])

The reference here has a special case: When types is a browser event object event, it means to remove (BIND) The delegate event Event.selector specified on the delegation node

The arguments passed in are events and the handler function
if (types && types.preventdefault && types.handleobj) {
  //(event) Dispatch ed jquery.event
  handleobj = types.handleobj;
  Types.delegatetarget is the event managed Object
  jquery (types.delegatetarget). Off (
   //combining jquery recognized type
   Handleobj.namespace? Handleobj.origtype + "." + HandleObj.namespace:handleObj.origType,
   handleobj.selector,
   Handleobj.handler
   );
  return this;
}

In any case, the JQuery.event.remove function is invoked to solve the binding event.

  JQuery.fn.off Complete source code is as follows

 Off:function (types, selector, fn) {var handleobj, type; The passed in parameter is an event and the handler function is bound to the if (types && types.preventdefault && types.handleobj) {//(event) dispatched J
  Query.event handleobj = types.handleobj; Types.delegatetarget is the event managed object jquery (Types.delegatetarget). Off (///combining jquery recognized type handleobj.namespace? handleob
  J.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, sel
  Ector, types[type]);
  return to 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, analyze the low-level API JQuery.event.remove for event binding.

JQuery.event.remove

jquery uses the. Off () function when an event bound by an injury is an internal call to the underlying function of JQuery.event.remove. The process flow of this function is as follows

1. Decompose the incoming event type types, traversal type, if the event to be deleted does not have an event name, only the namespace indicates that all binding events under that namespace are deleted

decomposes types to Type.namespace as an array of unit elements
types = (Types | | ""). Match (core_rnotwhite) | | [""];
t = types.length;
while (t--) {
   tmp = rtypenamespace.exec (types[t]) | | [];
   Type = Origtype = tmp[1];
   namespaces = (Tmp[2] | | ""). Split ("."). Sort ();

   types[all events on the current namespace (T]) of the current element (
   !type) {for
    (type in events) {
     jQuery.event.remove (elem, type + types[T], handler, selector, true);
    Continue;
   }
   ...

2. The traversal type process, deletes matches the event, the proxy counts revises

Type = (selector special.delegateType:special.bindType) | | type;
handlers = events[Type] | | [];
TMP = tmp[2] && new RegExp ("(^|\\.)" + namespaces.join ("\. (?:. *\\.|)") + "(\\.| $)" );
Delete matching event
Origcount = j = handlers.length;
while (j--) {
   handleobj = handlers[j];

   Various conditions for removing events can be removed
   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 handler for the specified type on the node is already empty, remove the event handling object of that type on the events

Remove event handling Objects
//(Remove potential infinite recursion during special event handling, the next chapter will specifically address this situation)
if (Origcount &&!handlers.length) {
//For example, VAR Js_obj = document.createelement ("div"); Js_obj.onclick = function () {...}
The js_obj above is a reference to a DOM element that has long been in the Web page and does not disappear, and this DOM element is a property of the onclick, the internal function reference (closure), and the anonymous function and the Js_ There is a hidden association (scope chain) between obj so that a circular reference is formed.
if (!special.teardown | | special.teardown.call (elem, namespaces, elemdata.handle) = = False) {
Jquery.removeeven T (elem, type, elemdata.handle);

Delete events[type];

4. If there are no bound events on the node, empty the event handling portal handle

if (Jquery.isemptyobject (events)) {
delete elemdata.handle;
Removedata also checks whether the event object is empty, so use it instead of the delete
jquery._removedata (elem, "events");
}

Expansion: Browser Event deletion jquery.removeevent

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 the memory leaks in ie6-8
    //DetachEvent The custom event needs to pass the first parameter, cannot be undefined
    if ( typeof elem[Name] = = = core_strundefined) {
     elem[name] = null;
    }
    Elem.detachevent (name, handle);
   }
;

The above content is small series to introduce the jquery 1.9.1 Source Analysis Series (10) Event System binding event, I hope you like.

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.