Alte Frage, aber immer noch keine gute aktuelle Antwort mit Insight Imo.
Heutzutage unterstützen alle Browser mouseover/mouseout
und mouseenter/mouseleave
. Trotzdem registriert jQuery Ihren Handler nicht bei mouseenter/mouseleave
, sondern legt ihn stillschweigend auf einen Wrapper, mouseover/mouseout
wie der folgende Code zeigt, und interpretiert ihn leicht anders mouseenter/mouseleave
.
Das genaue Verhalten von Ereignissen ist besonders für „Delegate-Handler“ relevant. Leider hat jQuery auch eine andere Interpretation dessen, was Delegiertenhandler sind und was sie für Ereignisse erhalten sollten. Diese Tatsache wird in einer anderen Antwort für das einfachere Klickereignis gezeigt.
Wie kann man also eine Frage zu jQuery richtig beantworten, das Javascript-Formulierungen für Ereignisse und Handler verwendet, aber beide unterscheidet und dies in seiner Dokumentation nicht einmal erwähnt?
Zuerst die Unterschiede in "echtem" Javascript:
- beide
- Die Maus kann von äußeren / äußeren Elementen zu inneren / innersten Elementen „springen“, wenn sie schneller bewegt wird, als der Browser seine Position abtastet
- Jeder
enter/over
bekommt eine entsprechende leave/out
(möglicherweise spät / nervös)
- Ereignisse gehen zum sichtbaren Element unter dem Zeiger (unsichtbar → kann kein Ziel sein)
mouseenter/mouseleave
- wird an das Element geliefert, an dem es registriert ist (Ziel)
- wann immer das Element oder ein Nachkomme (z. B. durch Springen) eingegeben / verlassen wird
- es kann nicht sprudeln, weil die Nachkommen konzeptionell als Teil des fraglichen Elements betrachtet werden, dh es gibt keine Kinder, von denen ein anderes Ereignis kommen könnte (mit der Bedeutung von "eingegeben / verlassen" der Elternteil?!)
- Bei Kindern sind möglicherweise auch ähnliche Handler registriert, die korrekt ein- / ausgehen, jedoch nicht mit dem Ein- / Ausstiegszyklus der Eltern zusammenhängen
mouseover/mouseout
- Das Ziel ist das eigentliche Element unter dem Zeiger
- Ein Ziel kann nicht zwei Dinge sein: dh nicht Eltern und Kind gleichzeitig
- Das Ereignis kann nicht „nisten“.
- Bevor ein Kind „überfordert“ werden kann, muss der Elternteil „raus“.
- kann sprudeln, da target / relatedTarget angibt, wo das Ereignis aufgetreten ist
Nach einigen Tests zeigt sich, dass die Emulation unnötig, aber vernünftig ist, solange Sie jQuery nicht verwenden, um Handler mit Selektorregistrierung zu delegieren: Sie filtert mouseover/mouseout
Ereignisse heraus, die a mouseenter/mouseleave
nicht erhalten würde. Das Ziel ist jedoch durcheinander. Der Real mouseenter/mouseleave
würde das Handler-Element als Ziel angeben, die Emulation könnte Kinder dieses Elements anzeigen, dh was auch immer das mouseover/mouseout
getragen wird.
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>