Jquery mouseenter() vs mouseover()
So after reading a recently answered question i am unclear if i really understand the difference between the mouseenter()
and mouseover()
. The post states
MouseOver():
Will fire upon entering an element and whenever any mouse movements occur within the element.
MouseEnter():
Will fire upon entering an element.
I came up with a fiddle that uses both and they seem to be quite similar. Can开发者_运维百科 someone please explain to me the difference between the two ?
I have also tried reading the JQuery definitions, both say the same thing.
The mouseover event is sent to an element when the mouse pointer enters the element
The mouseenter event is sent to an element when the mouse pointer enters the element.
Can someone please clarify with an example?
You see the behavior when your target element contains child elements:
http://jsfiddle.net/ZCWvJ/7/
Each time your mouse enters or leaves a child element, mouseover
is triggered, but not mouseenter
.
$('#my_div').bind("mouseover mouseenter", function(e) {
var el = $("#" + e.type);
var n = +el.text();
el.text(++n);
});
#my_div {
padding: 0 20px 20px 0;
background-color: #eee;
margin-bottom: 10px;
width: 90px;
overflow: hidden;
}
#my_div>div {
float: left;
margin: 20px 0 0 20px;
height: 25px;
width: 25px;
background-color: #aaa;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<div>MouseEnter: <span id="mouseenter">0</span></div>
<div>MouseOver: <span id="mouseover">0</span></div>
<div id="my_div">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Though they operate the same way, however, the mouseenter
event only triggers when the mouse pointer enters the selected element. The mouseover
event is triggered if a mouse pointer enters any child elements as well.
See the example code and demo at the bottom of the jquery documentation page:
http://api.jquery.com/mouseenter/
... mouseover fires when the pointer moves into the child element as well, while mouseenter fires only when the pointer moves into the bound element.
The mouseenter event differs from mouseover in the way it handles event bubbling. The mouseenter event, only triggers its handler when the mouse enters the element it is bound to, not a descendant. Refer: https://api.jquery.com/mouseenter/
The mouseleave event differs from mouseout in the way it handles event bubbling. The mouseleave event, only triggers its handler when the mouse leaves the element it is bound to, not a descendant. Refer: https://api.jquery.com/mouseleave/
This example demonstrates the difference between the mousemove, mouseenter and mouseover events:
https://jsfiddle.net/z8g613yd/
HTML:
<div onmousemove="myMoveFunction()">
<p>onmousemove: <br> <span id="demo">Mouse over me!</span></p>
</div>
<div onmouseenter="myEnterFunction()">
<p>onmouseenter: <br> <span id="demo2">Mouse over me!</span></p>
</div>
<div onmouseover="myOverFunction()">
<p>onmouseover: <br> <span id="demo3">Mouse over me!</span></p>
</div>
CSS:
div {
width: 200px;
height: 100px;
border: 1px solid black;
margin: 10px;
float: left;
padding: 30px;
text-align: center;
background-color: lightgray;
}
p {
background-color: white;
height: 50px;
}
p span {
background-color: #86fcd4;
padding: 0 20px;
}
JS:
var x = 0;
var y = 0;
var z = 0;
function myMoveFunction() {
document.getElementById("demo").innerHTML = z += 1;
}
function myEnterFunction() {
document.getElementById("demo2").innerHTML = x += 1;
}
function myOverFunction() {
document.getElementById("demo3").innerHTML = y += 1;
}
onmousemove
: occurs every time the mouse pointer is moved over the div element.onmouseenter
: only occurs when the mouse pointer enters the div element.onmouseover
: occurs when the mouse pointer enters the div element, and its child elements (p and span).
Old question, but still no good up-to-date answer with insight imo.
As jQuery uses Javascript wording for events and handlers, but does its own undocumented, but different interpretation of those, let me first shed light on the difference from the pure Javascript viewpoint:
- both event pairs
- 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 correspondingleave/out
(possibly late/jumpy) - events go to the visible element below the pointer (invisible elements can’t be target)
mouseenter/mouseleave
- does not bubble (event not useful for delegate handlers)
- the event registration itself defines the area of observation and abstraction
- works on the target area, like a park with a pond: the pond is considered part of the park
- the event is emitted on the target/area whenever the element itself or any descendant directly is entered/left the first time
- entering a descendant, moving from one descendant to another or moving back into the target does not finish/restart the
mouseenter/mouseleave
cycle (i.e. no events fire) - if you want to observe multiple areas with one handler, register it on each area/element or use the other event pair discussed next
- descendants of registered areas/elements can have their own handlers, creating an independent observation area with its independent
mouseenter/mouseleave
event cycles - if you think about how a bubbling version of
mouseenter/mouseleave
could look like, you end up with with something likemouseover/mouseout
mouseover/mouseout
- events bubble
- events fire whenever the element below the pointer changes
mouseout
on the previously sampled element- followed by
mouseover
on the new element - the events don’t “nest”: before e.g. a child is “overed” the parent will be “out”
target/relatedTarget
indicate new and previous element- if you want to watch different areas
- register one handler on a common parent (or multiple parents, which together cover all elements you want to watch)
- look for the element you are interested in between the handler element and the target element; maybe
$(event.target).closest(...)
suits your needs
Not-so-trivial mouseover/mouseout
example:
$('.side-menu, .top-widget')
.on('mouseover mouseout', event => {
const target = event.type === 'mouseover' ? event.target : event.relatedTarget;
const thing = $(target).closest('[data-thing]').attr('data-thing') || 'default';
// do something with `thing`
});
These days, all browsers support mouseover/mouseout
and mouseenter/mouseleave
natively. Nevertheless, jQuery does not register your handler to mouseenter/mouseleave
, but silently puts them on a wrappers around mouseover/mouseout
as the code below exposes.
The emulation is unnecessary, imperfect and a waste of CPU cycles: it filters out mouseover/mouseout
events that a mouseenter/mouseleave
would not get, but the target
is messed. 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.
For that reason I do not use jQuery for those events, but e.g.:
$el[0].addEventListener('mouseover', e => ...);
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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div id=outer>
<ul id=log>
</ul>
</div>
</body>
Note: For delegate handlers never use jQuery’s “delegate handlers with selector registration”. (Reason in another answer.) Use this (or similar):
$(parent).on("mouseover", e => {
if ($(e.target).closest('.gold').length) {...};
});
instead of
$(parent).on("mouseover", '.gold', e => {...});
精彩评论