JavaScript and JQuery's mouse mouse event bubbling processing

  • 2020-06-15 07:48:15
  • OfStack

Simple mouse movement events:

Enter the


mouseenter : no bubble
mouseover: The bubbling

mouseover events are triggered regardless of whether the mouse pointer passes through the selected element or its children
The mouseenter event is triggered only when the mouse pointer passes through the selected element

Removed from the


mouseleave: Don't bubble
mouseout : bubble

The mouseout event is triggered whether the mouse pointer leaves the selected element or any child element
The mouseleave event is triggered only when the mouse pointer leaves the selected element

Let's observe the problem through one case:

Bind an mouseout event to a nested hierarchy and you will find that the mouseout event is not what you would expect


<!DOCTYPE html><div class="out overout" style="width:40%;height:120px; margin:0 15px;background-color:#D6EDFC;float:left;" data-mce-style="width: 40%; height: 120px; margin: 0 15px; background-color: #d6edfc; float: left;"><p style="border:1px solid red" data-mce-style="border: 1px solid red;"> External child element </p><div class="in overout" style="width:60%;background-color:#FFCC00;margin:10px auto;" data-mce-style="width: 60%; background-color: #ffcc00; margin: 10px auto;"><p style="border:1px solid red" data-mce-style="border: 1px solid red;"> Inner child element </p><p id="inshow">0</p>
    </div><p id="outshow">0</p>
</div><script type="text/javascript">     var i = 0;
    var k = 0;     document.querySelectorAll('.out')[0].addEventListener('mouseout',function(e){
        document.querySelectorAll("#inshow")[0].textContent = (++i)
       e.stopPropagation();
    },false)    document.querySelectorAll('.in')[0].addEventListener('mouseout',function(){
       document.querySelectorAll("#outshow")[0].textContent = (++k)
    },false) </script>

We found a problem with the mouseout event:

1. Nothing can stop the bubbling
2. It also fires on internal child elements

The same problem with the mouseover event, how do we stop the bubble if the stopPropagation method fails?

1. In order to prevent repeated triggering of mouseover and mouseout, one attribute of the event object, relatedTarget, is used here. This attribute is used to determine the related nodes of the mouseover and mouseout event target nodes. Simply put, when the mouseover event is triggered, the relatedTarget attribute represents the node to which the mouse has just left, and when the mouseout event is triggered it represents the object to which the mouse moved. Since MSIE does not support this attribute, it does have an alternate attribute, fromElement and toElement, respectively.
2. With this property, we can know exactly where our mouse is moving and from which object. This allows us to determine whether the associated object is inside the object we want to trigger the event, or whether it is the object itself. With this judgment we can make a reasonable choice as to whether or not to actually trigger the event.
3. Here we also use the contains method, which is used to check whether one object is included in another object. MSIE and FireFox provide checking methods, respectively, which encapsulate a function.

jQuery's treatment is also like a rut


jQuery.each({
        mouseenter: "mouseover",
        mouseleave: "mouseout",
        pointerenter: "pointerover",
        pointerleave: "pointerout"
    }, function(orig, fix) {
        jQuery.event.special[orig] = {
            delegateType: fix,
            bindType: fix,             handle: function(event) {
                var ret,
                    target = this,
                    related = event.relatedTarget,
                    handleObj = event.handleObj;                 // For mousenter/leave call the handler if related is outside the target.
                // NB: No relatedTarget if the mouse left/entered the browser window
                if (!related || (related !== target && !jQuery.contains(target, related))) {
                    event.type = handleObj.origType;
                    ret = handleObj.handler.apply(this, arguments);
                    event.type = fix;
                }
                return ret;
            }
        };
    });


Related articles: