Jquery mouseenter() vs mouseover()

前端 未结 7 2134
梦如初夏
梦如初夏 2020-11-22 07:58

So after reading a recently answered question i am unclear if i really understand the difference between the mouseenter() and mouseover(). The post

7条回答
  •  既然无缘
    2020-11-22 08:35

    Old question, but still no good up-to-date answer with insight imo.

    These days, all browsers support mouseover/mouseout and mouseenter/mouseleave. Nevertheless, jQuery does not register your handler to mouseenter/mouseleave, but silently puts them on a wrappers around mouseover/mouseout as the following code shows and makes its own slightly different interpretation of mouseenter/mouseleave.

    The exact behavior of events is especially relevant on “delegate handlers”. Unfortunately, jQuery also has its own different interpretation of what delegate handlers are and what they should receive for events. That fact is shown in another answer for the simpler click event.

    So how to properly answer a question about jQuery, which uses Javascript wording for events and handlers, but makes both different and does not even mention that in its documentation?

    First the differences in “real” Javascript:

    • both
      • the mouse can “jump” from outside/outer elements to inner/innermost elements when moved faster than the browser samples its position
      • any enter/over gets a corresponding leave/out (possibly late/jumpy)
      • events go to the visible element below the pointer (invisible → can’t be target)
    • mouseenter/mouseleave
      • is delivered to the element where registered (target)
      • whenever the element or any descendant (e.g. by jumping) is entered/left
      • it can’t bubble, because conceptually the descendants are considered part of the element in question, i.e. there are no children where another event could come from (with the meaning of “entered/left” the parent?!)
      • children might also have similar handlers registered, which enter/leave correctly, but unrelated to the parental enter/leave cycle
    • mouseover/mouseout
      • the target is the actual element below the pointer
        • a target can’t be two things: i.e. not parent and child at the same time
      • the event can’t “nest”
        • before a child could be “overed”, the parent needs to get “out”
      • can bubble, because target/relatedTarget indicate where the event occurred

    After some testing, it shows that as long as you don’t use jQuery “delegate handlers with selector registration”, the emulation is unnecessary but reasonable: It filters out mouseover/mouseout events that a mouseenter/mouseleave would not get. The target is messed, though. The real mouseenter/mouseleave would give the handler element as target, the emulation might indicate children of that element, i.e. whatever the mouseover/mouseout carried.

    const list = document.getElementById('log');
    const outer = document.getElementById('outer');
    const $outer = $(outer);
    
    function log(tag, event) {
      const li = list.insertBefore(document.createElement('li'), list.firstChild);
      // only jQuery handlers have originalEvent
      const e = event.originalEvent || event;
      li.append(`${tag} got ${e.type} on ${e.target.id}`);
    }
    
    outer.addEventListener('mouseenter', log.bind(null, 'JSmouseenter'));
    $outer.on('mouseenter', log.bind(null, '$mouseenter'));
    div {
      margin: 20px;
      border: solid black 2px;
    }
    
    #inner {
      min-height: 80px;
    }
    
    
    
      

提交回复
热议问题