An Event System Based on Event proxy has been built in recent days, but even event proxy still depends on event registration. Therefore, we have thoroughly studied jquery's Event System and sorted it out and shared it.
Due to the awkwardness between IE and the standard browser, we can block the difference by making a function called addevent. The following is a classic addevent function:
VaR addevent = function (OBJ, type, FN) {If (obj. addeventlistener) obj. addeventlistener (type, FN, false); else if (obj. attachevent) {OBJ ["E" + Type + FN] = FN; obj. attachevent ("On" + type, function () {OBJ ["E" + Type + FN] () ;}};
However, this concise function has many disadvantages. For example, it cannot handle the execution sequence of the callback function bound to IE, nor can it eliminate the differences between event objects. Therefore
// Http://dean.edwards.name/weblog/2005/10/add-event///http://dean.edwards.name/weblog/2005/10/add-event2/function addevent (element, type, Handler) {// assign each event handler a unique ID // bind a uuid if (! Handler. $ guid) handler. $ guid = addevent. guid ++; // create a hash table of event types for the element // set a special attribute on the element node to bind the event to store the event if (! Element. events) element. events = {}; // create a hash table of Event Handlers for each element/event pair // The type name of the event in the evets function, or, the event is handled by type based on VaR handlers = element. events [type]; If (! Handlers) {handlers = element. events [type] ={}; // store the existing event handler (if there is one) if (element ["on" + type]) {handlers [0] = element ["on" + type]; // dom1.0 }}// store the event handler in the hash table // set a type to correspond to multiple callback functions handlers [handler. $ guid] = handler; // assign a global event handler to do all the work element ["on" + type] = handleevent ;}; // a counter used to create unique idsaddevent. guid = 1; function removeevent (element, type, Handler) {// Delete the event handler from the hash table if (element. events & element. events [type]) {// remove the delete element of a callback function corresponding to the current type. events [type] [handler. $ guid] ;}}; function handleevent (event) {var returnvalue = true; // grab the event object (ie uses a global event object) event = event | fixevent (window. event); // get a reference to the hash table of Event Handlers var handlers = This. events [event. type]; // execute each event handler for (var I in handlers) {This. $ handleevent = handlers [I]; If (this. $ handleevent (event) === false) {returnvalue = false ;}} return returnvalue ;}; function fixevent (event) {// Add W3C standard event Methods Event. preventdefault = fixevent. preventdefault; event. stoppropagation = fixevent. stoppropagation; return event;}; fixevent. preventdefault = function () {This. returnvalue = false ;}; fixevent. stoppropagation = function () {This. cancelbubble = true ;};
perfectly solves the IE execution sequence problem and adds two methods preventdefault and stoppropagation to the IE event object. jquery's event system is developed based on it. The following Code of jquery1.0.1:
Event: {// bind an event to an element // original by Dean Edwards Add: function (element, type, Handler) {// for whatever reason, IE has trouble passing the window object // around, causing it to be cloned in the process if (jquery. browser. MSIE & element. setinterval! = Undefined) element = Window; // make sure that the function being executed has a unique ID if (! Handler. guid) handler. guid = This. guid ++; // init the element's event structure if (! Element. events) element. events = {}; // get the current list of functions bound to this event var handlers = element. events [type]; // if it hasn' t been initialized yet if (! Handlers) {// init the event handler queue handlers = element. events [type] ={}; // remember an existing handler, if it's already there if (element ["on" + type]) handlers [0] = element ["on" + type];} // Add the function to the element's handler list handlers [handler. guid] = handler; // and bind the global event handler to the element ["on" + type] = This. handle; // The above is basically the same as that of DC. // remember T He function in a global list (for triggering) if (! This. global [type]) This. global [type] = []; this. global [type]. push (element) ;}, guid: 1, global :{}, // detach an event or set of events from an element remove: function (element, type, Handler) {If (element. events) if (type & element. events [type]) if (handler) delete element. events [type] [handler. guid]; else for (var I in element. events [type]) delete element. events [type] [I]; else for (VAR J in ele Ment. Events) This. Remove (element, j) ;}, // trigger. Why not call it fire ?! Trigger: function (type, Data, element) {// touch up the incoming data Data = data | []; // handle a global trigger if (! Element) {var G = This. global [type]; If (g) for (VAR I = 0; I <G. length; I ++) This. trigger (type, Data, G [I]); // handle triggering a single element} else if (element ["on" + type]) {// pass along a fake event data. unshift (this. fix ({type: type, target: Element}); // trigger the event element ["on" + type]. apply (element, data) ;}}, handle: function (event) {If (typeof jquery = "undefined") Re Turn; event = event | jquery. event. Fix (window. Event); // if no correct event was found, fail if (! Event) return; var returnvalue = true; var c = This. events [event. type]; for (var j in c) {If (C [J]. apply (this, [event]) === false) {event. preventdefault (); event. stoppropagation (); returnvalue = false ;}} return returnvalue ;}, fix: function (event) {If (event) {event. preventdefault = function () {This. returnvalue = false;}; event. stoppropagation = function () {This. cancelbubble = true ;};} return event ;}}
Let's take a look at this classic Event System Based on Event registration. A few years ago, the mainstream event system was based on this. First, set one or several top-level objects to manage event handles and related items. Here, as we can see, a global object is used. It loads elements because it is based on event registration, and the callback functions are directly bound to the elements. Later, IE7 amplified the memory leakage problem and jquery further improved, during the unload operation, all the events above the elements that have registered the event are removed. On these elements, there is a custom property called events, which is an object, and the callback function bound to it by event-type management, the purpose is to allow events to be executed in the order of binding. When we trigger an event, we do not directly execute the bound callback function, because here we use the dom0 event method, no matter how many events of the same type are bound, at last, only one of this type is used. Therefore, they are all put into a handle function (De's handleevent ). Handle does three things to make the event object always the first parameter of the function, transform the event object, and execute the established callback function in order. Finally, we noticed that it has a return value, which is used to determine whether it executes the default behavior of the browser.
I have read all the versions of jquery1.0.4, just a few versions. Several binding methods have been added to jquery1.1, the famous one, and toggle, hover, and ready have been greatly improved. In jquery, there are basically two versions of a method, one is the static method of the jquery namespace, and the other is the instance method of the jquery object. The instance method corresponds to multiple elements (because jquery usually contains several DOM elements), while the static method corresponds to one element. All instance methods call these static methods to the periphery, so the static method has a high position. The improvement focuses on these static methods, so I will focus on them. If you are interested, let's take a look at jquery1.1. At this time, John resig began to solve the issue of event object difference and added pagex, Pagey, and target attributes for the IE event object. The unbind and one events are quite dumb, because all events are managed by top-level objects and the events of top-level objects are deleted, that is, unbind. After deletion, the unbind will continue to be executed by a copy-and-receive shell. Hover is a little complicated because it hasn't done relatedtarget in advance.
because the Event System is a complicated thing, I have not started to talk about the latest version of jquery, and it has reached such a length. Finally, let's summarize the jquery event running process: bind an event to the element) => Add => set UUID for the callback function => hand to top-level Object Management => handle => fix => start to wait for the user to trigger the event or directly call the trigger.