The event of the final incoming event handler has actually been standardized by JQuery,
Its original event object is stored in the Originalevent property of the event object.
Each event is an instance of Jquery.event, with six methods stored in its prototype chain.
The code is as follows |
Copy Code |
JQuery.Event.prototype = { Preventdefault:function () { Cancel event default behavior }, Stoppropagation:function () { Cancel event bubbling up }, Stopimmediatepropagation:function () { this.isimmediatepropagationstopped = Returntrue; This.stoppropagation (); }, Isdefaultprevented:returnfalse, Ispropagationstopped:returnfalse, Isimmediatepropagationstopped:returnfalse }; |
For canceling event default behavior and bubbling up everyone is certainly not unfamiliar, let's focus on the third method,
From the source we know that it calls the Stoppropagation method, so his first role is to cancel bubbling.
The code is as follows |
Copy Code |
for (i = 0; i < handlerqueue.length &&!event.ispropagationstopped (); i++) { matched = handlerqueue[I]; ... for (j = 0; J < matched.matches.length &&!event.isimmediatepropagationstopped (); j + +) { ... } } |
Let me start with a brief description of JQuery's event-binding mechanism, which will give you a better understanding of his second role.
Event handlers that are bound using jQuery are stored in the events object corresponding to the node in their type and binding order,
When an event is triggered, use $._data to remove the handler queue for the corresponding event in the events for subsequent traversal execution.
In the matched.matches of the inner loop, the event handler queue that the current node needs to execute when the event is triggered is saved.
So when isimmediatepropagationstopped is true, the subsequent event handlers for that node are prevented from executing under the current event.
Finally, a simple
The code is as follows |
Copy Code |
<! DOCTYPE html> <meta charset= "GBK" > Brief analysis of <title>jquery event object </title> <body> <a id= "j_btn" href= "javascript:;" > Point me! </a> <script type= "Text/javascript" src= ". /js/lib/jquery.js "></script> <script type= "Text/javascript" > $ ("Body"). Delegate ("#J_btn", "click", Function () { Alert ("Bubbling to Body"); }); var $btn = $ ("#J_btn"); $btn. Click (Function (event) { Event.stopimmediatepropagation (); Alert ("First click"); }); $btn. Click (function () { Alert ("Second Click"); }); </script> </body>
|
Hope to help you better understand!
Jquery.event Event Mechanism Focusin/focusout event
First look at the Jquery.simulate () method, which implements a bubbling event based on a native event. The source code is as follows:
The code is as follows |
Copy Code |
Simulate:function (type, Elem, event, bubble) { var evt = jquery.extend (New Jquery.event (), Event, { Type:type, Issimulated:true, Originalevent: {} } );
if (bubble) { JQuery.event.trigger (evt, NULL, elem); Direct program trigger, this can be bubbling } else { JQuery.event.dispatch.call (Elem, evt); }
if (evt.isdefaultprevented ()) { Event.preventdefault (); Because of impersonation, the underlying object should be changed at the same time } } |
The principle of focusin/focusout bubbling event is to monitor the Focus/blur action of a particular element during the event capture phase, and the capture behavior occurs on the Document object in order to effectively implement events that all elements can bubble. Once the program monitors for the presence of Focus/blur behavior, an event handler bound to the document element is triggered that invokes the simulate logic triggering event bubbling internally to achieve the bubbling event we want. The source code is as follows:
The code is as follows |
Copy Code |
Jquery.each ({focus: "Focusin", Blur: "Focusout"}, Function (orig, fix) { var attaches = 0, Handler = function (event) { JQuery.event.simulate (fix, Event.target, JQuery.event.fix (event), true); };
Jquery.event.special[fix] = { Setup:function () { if (attaches++ = = 0) { Document.addeventlistener (orig, Handler, true); Add event sniffing during the capture phase of the Focus/blur event to monitor directly on the document while preventing excessive binding } }, Teardown:function () { if (--attaches = = 0) { Document.removeeventlistener (orig, Handler, true); } } }; }); |
Let's analyze the process by which we apply focusin in order to understand its behavior more clearly.
The code is as follows |
Copy Code |
$ ("P"). Focusin (function () { Alert (' yes! '); }); |
When we first add an event handler to the Focusin event, JQuery adds the handler function to the document. After each user triggers the focus event, the browser captures the event and triggers the handler function at the first time, and the handler function simulates the event bubbling process (trigger) within it, thereby implementing a bubbling event.
The relevant logic of the Focusin/focus event pair in the trigger method. The source code is as follows:
The code is as follows |
Copy Code |
Trigger:function (event, data, Elem, onlyhandlers) { // .... Rfocusmorph =/^ (?: Focusinfocus|focusoutblur) $/, This is used to avoid: When triggering elem.focus default behavior, the focusin behavior is triggered two times because it has been executed. if (rfocusmorph.test (type + jQuery.event.triggered)) { Return } // .... Special events, mainly to solve the focus mechanism. If trigger returns FALSE, it returns directly Special = Jquery.event.special[type] | | {}; if (!onlyhandlers && special.trigger && special.trigger.apply (elem, data) = = False) { Return } if (!onlyhandlers &&!special.nobubble &&!jquery.iswindow (elem)) { var bubbletype = Special.delegatetype | | Type if (!rfocusmorph.test (Bubbletype + type)) { Type= Focus/blur This can trigger both focus and Focusin events on the Elem cur = cur.parentnode; } // ... } // .... }, |
One: To avoid triggering the Focusin event twice, when we execute Elem.focus (), document captures the event again and attempts to trigger the Focusin event again.
The code is as follows |
Copy Code |
if (rfocusmorph.test (type + jQuery.event.triggered)) {return;} |
II: When trigger (' focus '), apply the native event as much as possible, but not bubbling.
The code is as follows |
Copy Code |
if (!onlyhandlers && special.trigger && special.trigger.apply (elem, data) = = False) { Return } |
Third: If the conditions for applying native events are not met, the focus and Focusin events are triggered on the current element and bubbled up in Focusin type events.
The code is as follows |
Copy Code |
var bubbletype = Special.delegatetype | | Type Type= Focus/blur, which can trigger both focus and Focusin events on the Elem if (!rfocusmorph.test (Bubbletype + type)) {cur = cur.parentnode;} Event.type = i > 1? BubbleType:special.bindType | | Type |
Ii. Mouseenter/mouseleave higher-order events
Mouseenter/leave higher-order events depend on the special[' MouseEnter '].handle method for implementation. In this method, there will be the logic of the procedure, if the program to determine the current MouseOver event to meet the specific conditions, the event becomes a MouseEnter event, the corresponding event handler is invoked.
Mouseenter/leave higher-order events depend on the native Mouseover/mouseouter event, as shown in the figure:
The source code of its handle method is as follows:
The code is as follows |
Copy Code |
Handle:function (event) { var ret, target = this, Related = Event.relatedtarget, Handleobj = Event.handleobj; //If related is outside the target. /No Relatedtarget if the mouse left/entered the browser window //If passed trigger (' MouseEnter ') or trigger (' mouseover ') will also satisfy the condition if (!rela Ted | | (Related!== target &&!jquery.contains (target, related)) { event.type = handleobj.origtype; //The type of event must be corrected before the event handler is executed ret = HandleObj.handler.apply (this, arguments); event.type = fix; } return ret; }//If this is a higher order event, the method that invokes the High-order event. Internal judgment Logic ret = ((jquery.event.special[handleobj.origtype) | | {}). Handle | | Handleobj.handler). Apply (Matched.elem, args); Event.type = i > 1? BubbleType:special.bindType | | Type
Handle = (Jquery._data (cur, "events") | | {}) [Event.type] && jquery._data (cur, "handle"); Higher-order events depend on the underlying event (native event) whose structure depends on the delegatetype or Bindtype if (handle) { Handle.apply (cur, data); } |
Observe the source code we can find that when the program triggers higher-order events, such as Trigger (' MouseEnter '), actually need to trigger the corresponding native event. As a result, the results of the following code will make you a refreshing one, because the mouseenter you bind here will respond:
code is as follows |
copy code |
var $inner = $ (' #inner '); var $outer = $ (' #outer '); $inner. On (' MouseOver ', function () { $ (this). CSS (' backgroundcolor ', ' #444 '); }); $inner. On (' MouseEnter ', function (event) { alert (event.relatedtarget); }); $outer. On (' MouseEnter ', function () { var $this = $ (this); $this. CSS (' BackgroundColor ', ' #000 '); }); $ ("P"). Click (function () {$inner. Trigger (' MouseEnter ');}); |
Third, browser compatibility correction
Depending on the postdispatch logic, the simulate () method is invoked to implement the bubbling of the event.
The end of this article.