JQuery3.1.1 Source code Interpretation (13) "Event-on"

Source: Internet
Author: User
Tags decrypt extend

Through the previous chapter for the introduction of the Addevent library, its compatibility is super-good, it is said that for IE4, 5 have a good compatibility, which is consistent with the principle of jquery, and in jquery, there is an object and its relative, that is the event.

The last chapter has already said, this jQuery.fn.on function is finally through the Jquery.event object's Add method to implement the function, of course, the method is not limited to add, the following will be detailed introduction of these methods. about Jquery.event

This is a method on the JQuery object, it does a lot of optimization events, such as compatibility issues, storage optimization problems.

Jquery.event = {
  global = {},
  add:function () {...},
  remove:function () {...},
  dispatch:function () {...} },
  handlers:function () {...}, addprop:function () {...},
  fix:function () {...},
  special:function () { ...}
}

Above is the function of the event, where: Add () is the addition of an event function, listening to events on the current DOM, generating a handler function; remove () removes the event; dispatch () is the actual event performer; handlers () in dispatch execution, The event is corrected to distinguish between native and delegate events; Addprop () is a binding parameter to an object; fix () Fixes a native event event to an object that is readable and writable and has a uniform interface; Special () is a special event table.

Before saying the Add function, it was tempting to savor the addevent Library of Dean Edwards ' great God, even though he had already spoken:

function addevent (element, type, handler) {//Add an identity GUID to each of the functions to be bound if (!handler.$ $guid) handler.$ $guid = Addevent.gu
  id++;
  Creates an event object on the bound object event if (!element.events) element.events = {};
  A type corresponds to a handlers object, such as click to handle multiple functions at the same time var handlers = Element.events[type];
    if (!handlers) {handlers = Element.events[type] = {};
    If the onclick already exists a function, take over if (element["on" + type]) {handlers[0] = element["on" + type];
  }}//Prevent duplicate bindings, each corresponding to a GUID handlers[handler.$ $guid] = handler;
Replace the onclick function with Handleevent element["on" + type] = Handleevent;
};

Initial GUID addevent.guid = 1; function removeevent (element, type, handler) {//delete the event handler from the hash table if (element.events &amp
  ;& Element.events[type]) {delete element.events[type][handler.$ $guid];

}//Feel the back is not to add a judgment, when Element.events[type] is empty, together deleted}; function Handleevent (event) {//Grab the event object (IE uses a global event object) event = Event | | window. event;
  Here the this points to element var handlers = This.events[event.type]; Execute every event handler for (Var i in handlers) {//Here is a small trick, why not execute directly, but first bind to this after execution//is for the function to execute when the internal th
    is points to element this.$ $handleEvent = handlers[i];
  this.$ $handleEvent (event); }
};

If we support AddEventListener for this browser, we can make a slight change to the Addevent function (attachevent compatibility is not considered), at the end of the Addevent function, if the code is modified to the following:

Element["on" + type] = Handleevent;
if (!element.hasaddlistener) {
  element.addeventlistener (type,handleevent,false);
  Listen for events Just add one more time
  element[' hasaddlistener ' = true;
}

Although the above approach is a bit repetitive, the basic logic needs to be judged, but this is very close to the event Add method in JQuery. In other words, the previous logic was to bind all the listening methods through AddEventListener, bind one, bind two, and now the idea changed: If we write a handler function (handleevent), this handler is used to handle events bound to the DOM, and add it through AddEventListener (just add it once), which is the basic logic of event handling in JQuery (I understand, please correct me).

Understand the nature of the delegate event: Listen for events on the parent DOM, and event handlers find the corresponding child DOM to handle. jQuery.event.add Function Analysis

Well, to directly see the source code, I have more than once mentioned that the best way to learn the source code is to debug, debugging the best way is 100% test cases.

Jquery.event = {global: {}, Add:function (Elem, types, handler, data, selector) {var handleobjin, Eventhandle , TMP, events, T, Handleobj, special, handlers, type, namespaces, Origtype,//jQuery Create a data CAC specifically for events

    He:datapriv elemdata = Datapriv.get (elem);
    Elem a problem, exit the IF (!elemdata) {return directly;
      }//If handler is an event-handling object and has handler property if (handler.handler) {Handleobjin = handler;
      handler = Handleobjin.handler;
    selector = Handleobjin.selector; }//Ensure that invalid selectors throw exceptions at attach time//Evaluate against documentelement in case El EM is a non-element node (e.g., document) if (selector) {jQuery.find.matchesSelector (documentelement, select
    OR);
    }//GUID.
    if (!handler.guid) {handler.guid = jquery.guid++;
}//Initialize Data.elem events and handle if (! (events = elemdata.events)) {events = Elemdata.events = {};    } if (! (Eventhandle = elemdata.handle)) {eventhandle = Elemdata.handle = function (e) {//FINAL
          The execution here, after clicking Click, will execute this function return typeof jQuery!== "undefined" && jQuery.event.triggered!== e.type?
      JQuery.event.dispatch.apply (Elem, arguments): undefined;
    }; }//Handle multiple events such as ("click Mouseout"), spaces separated by types = (Types | | ""). Match (rnothtmlwhite) | |
    [ "" ];
    t = types.length; Each event is processed while (t--) {tmp = Rtypenamespace.exec (types[t]) | |
      [];
      Type = Origtype = tmp[1]; namespaces = (tmp[2] | | ""). Split (".").

      Sort ();
      There *must* be a type, no attaching namespace-only handlers if (!type) {continue; }//Special Handling Special = jquery.event.special[Type] | |

      {}; IF selector defined, determine special event API type, otherwise given type type = (selector? special.delegatet Ype:special.bindType) | |

      Type Update SpecIal based on newly reset type special = jquery.event.special[Type] | |

      {}; Handleobj is passed to all event handlers Handleobj = Jquery.extend ({type:type, Origtype:orig Type, Data:data, Handler:handler, Guid:handler.guid, Selector:selector, NEEDSC
      Ontext:selector && jQuery.expr.match.needsContext.test (selector), Namespace:namespaces.join (".")

      }, Handleobjin);
        If the Click event was not previously added, if (! (handlers = events[type])) {handlers = events[type] = [];

        Handlers.delegatecount = 0; Only use AddEventListener if the special events handler returns false//AddEventListener event is also just added once if
          (!special.setup | |
            Special.setup.call (Elem, data, namespaces, eventhandle) = = = False) {if (Elem.addeventlistener) {
     Eventhandle is the event handler function Elem.addeventlistener (type, eventhandle);     }}} if (Special.add) {Special.add.call (Elem, handleobj);
        if (!handleobj.handler.guid) {handleObj.handler.guid = Handler.guid; }}//Added to the event list, delegates to precede if (selector) {handlers.splice (handlers.delegatecount++, 0,
      Handleobj);
      } else {Handlers.push (handleobj);
    }//The surface has been added jquery.event.global[type] = true; }

  }
}

To start with the code, you've already said Data in JQuery, there are two of them:

For DOM event 
var datapriv = new Data ();
Universal
var datauser = new Data () in JQuery;

Datapriv caches two objects based on the current elem, namely events and handle, the handle is the one that is added through AddEventListener, and events stores more things, such as I bind a click event, then events[' click ' = [], it is an array, this time no matter how many click events I bind, just want to add content in this array, add the time to consider a certain order. So, what is the length of each child element of the array:

Handleobj = {
  Type:type,
  origtype:origtype,
  data:data,
  Handler:handler,
  Guid:handler.guid,
  selector:selector,
  needscontext:selector && jQuery.expr.match.needsContext.test (selector),
  namespace:namespaces.join (".")
}

compatibility, compatibility, compatibility, in fact, the Add event mainly takes into account a lot of details of the content, if these are not open, let us compare the Event.add function and the addevent function the same point:

The left is the contents of the addevent function
addevent = = JQuery.event.add;
Handleevent = = Eventhandle;
handler.$ $guid = = Handler.guid;
Element.events = = datapriv[elem].events;

Very much like. jQuery.event.dispatch Function Analysis

When there is selector, the Add function handles adding events, and the execution of the event depends on dispatch. For example, in $ (' body '). On (' Click ', ' #test ', FN), we click on the body, will be monitored, the dispatch function will be executed, but FN does not execute unless we click #test. Probably Dispath is used to judge whether Event.target is the one that needs it.

JQuery.event.extend ({dispatch:function (nativeevent) {//Nativeevent becomes writable, JQuery-approved event var event =

    JQuery.event.fix (nativeevent); 
      var i, J, ret, matched, handleobj, handlerqueue, args = new Array (arguments.length),//Search processing events from data cache Handlers = (Datapriv.get (This, "events") | | {}) [Event.type] | | [], special = jquery.event.special[Event.type] | |

    {};

    Use the Fix-ed jquery.event rather than the (read-only) native event args[0] = event;
    for (i = 1; i < arguments.length; i++) {args[i] = arguments[i];

    } event.delegatetarget = this; Call the Predispatch hooks for the mapped type, and let it bail if desired if (Special.predispatch && speci
    Al.preDispatch.call (this, event) = = = False) {return;

    }//For handlers processing, differentiate the event type, and arrange in order Handlerqueue = JQuery.event.handlers.call (This, event, handlers); Run delegates first; They want to stop Propagation beneath us i = 0; while ((matched = handlerqueue[i++]) &&!event.ispropagationstopped ()) {Event.currenttarget = matched

      . Elem;
      j = 0; Execute while ((Handleobj = matched.handlers[j + +) &&!event.isimmediatepropa in the order in which handlers is queued Gationstopped ()) {//triggered event must either 1) have no namespace, or 2) with namespace (s)//a Sub
        Set or equal to those in the bound event (both can has no namespace).
          if (!event.rnamespace | | event.rnamespace.test (handleobj.namespace)) {event.handleobj = Handleobj;
          Event.data = Handleobj.data; The final execution is here ret = ((jquery.event.special[Handleobj.origtype] | |
            {}). Handle | |

          Handleobj.handler). Apply (Matched.elem, args);
              if (ret!== undefined) {if ((Event.result = ret) = = = False) {///The following two functions are events after event transformation
 Event.preventdefault ();             Event.stoppropagation ();  }}}}}//Call the Postdispatch hooks for the mapped type if (special.postdispatch
    {Special.postDispatch.call (this, event);
  } return Event.result; }
} );

The logic of event.handlers is also very complex, and I read, also did not understand, roughly is to bind all the events on the Elem, in a certain order to distinguish their execution order. Summary

It took a few days to look at a fur, especially the logic of the event, and it felt so complicated. It's the only way. Reference

JQuery 2.0.3 Source Analysis Event Architecture

Decrypt jquery Event Core-binding design (i)

Decrypt jquery Event Core-commissioned Design (ii)

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.