Event model
Speaking of events, it goes back to the "browser war" between Netscape and Microsoft. At that time, there was no standard for event models, and the two companies' implementations were the de facto standard. Netscape implemented an "event capture" event system in Navigator, while Microsoft implemented a basically opposite event system in IE called "event bubbling." The difference between these two systems is that when an event occurs, the priority of the relevant elements in processing (responding to) the event is different.
The following examples illustrate the differences between these two event mechanisms. Assume that the document has the following structure:
Because of these three The elements are nested, so clicking a actually clicks span and div. In other words, all three elements should have the opportunity to handle click events. Under the event capture mechanism, the priority of processing this click event is: div > span > a; while under the event bubbling mechanism, the priority of processing this click event is: a > span > div .
Later, the W3C specification required browsers to support both capturing and bubbling mechanisms, and allowed developers to choose which stage to register events to. So there is the following standard method of registering events:
target.addEventListener(type, listener, useCapture Optional);
where:
◆ type: string, Indicates the type of event to be monitored
◆ listener: listener object (JavaScript function), which can be notified when the specified event occurs
◆ useCapture: Boolean value, whether to register in the capture phase
In actual application development, in order to ensure compatibility with IE (because it does not support capture), useCapture is generally specified as false (the default value is also false). In other words, only register events to the bubbling stage; for the simple example above, the response order is: a > span > div.
Side effects of bubbling As mentioned above, IE’s bubbling event model has basically become the de facto standard. But bubbling has a side effect.
Still taking the previous document structure as an example, assuming it is a menu item in the interface, we want the menu to be hidden when the user mouse leaves the div. So, we registered a mouseout event for the div. If the user mouses away from the div, then everything is correct. And if the user mouse leaves from a or span, the problem arises. Because due to event bubbling, the mouseout events dispatched from these two elements will be propagated to the div, causing the mouse to not leave the div and the menu to be hidden in advance.
Of course, the side effects of bubbling are not difficult to avoid. For example, register the mouseout event for each element inside the div, and use the .stopPropagation() method to prevent the event from spreading further. For IE, you have to set the cancelBubble property of the event object to false to cancel event bubbling. However, this still falls back on the old path of dealing with browser incompatibility issues yourself.
Optimization plan In order to avoid the side effects of bubbling, jQuery provides mouseenter and mouseleave events, use them instead of mouseover and mouseout.
The following is excerpted from jQuery’s internal function withinElement, which provides support for mouseenter and mouseleave. The comments have been translated for your reference only.
// The following function is used to detect whether the event occurs in Inside another element
// Use
var withinElement = function( event ) {
// Check whether mouse(over|out) is still there in jQuery.event.special.mouseenter and mouseleave handlers Within the same parent element
var parent = event.relatedTarget;
// Set the correct event type
event.type = event.data;
// Firefox sometimes assigns a XUL to relatedTarget Element
// For this element, its parentNode attribute cannot be accessed
try {
// Chrome is similar, although the parentNode attribute can be accessed
// but the result is null
if ( parent && parent !== document && !parent.parentNode ) {
return;
}
// Up the DOM tree
while ( parent && parent !== this ) {
parent = parent.parentNode;
}
if ( parent !== this ) {
// If it is actually located on a non-child element, then fine, handle the event
jQuery.event.handle .apply( this, arguments );
}
// It is assumed that the element has been left, because the mouse is probably placed on a XUL element
} catch(e) { }
},
Conclusion
In jQuery, you can use mouseenter and mouseleave events to avoid the side effects of event bubbling.
Original text: http://www.ituring.com.cn/article/420