jQuery / Méthode / .hover() - Entrée, sortie et remplacement par on

Dans jQuery, .hover() est un raccourci pour enregistrer des fonctions quand le pointeur entre dans un élément et en sort. Elle est obsolète depuis jQuery 3.3 ; préférez .on("mouseenter", ...) et .on("mouseleave", ...) pour du nouveau code. Obsolète ne signifie pas supprimée : les deux approches ci-dessous ont été exécutées avec 3.7.1 et 4.0.0.

Deux fonctions ou une fonction commune

La forme à deux fonctions de .hover() appelle la première à l'entrée et la seconde à la sortie. Elle enregistre mouseenter et mouseleave, pas un événement nommé hover.

Ancienne forme Remplacement Signification
.hover(enter, leave) .on("mouseenter", enter).on("mouseleave", leave) Fonctions séparées pour entrée et sortie
.hover(handler) .on("mouseenter mouseleave", handler) Une fonction pour les deux événements

mouseenter concerne la frontière de l'élément. Depuis l'intérieur d'un parent, aller sur son enfant span ne constitue pas une nouvelle entrée dans le parent. Cela diffère de mouseover propagé depuis les transitions des enfants et évite ces appels répétés indésirables.

Exemple complet comparant hover et on

Enregistrez tout le code en UTF-8 dans hover-demo.html et ouvrez-le dans un navigateur. Internet est nécessaire pour charger le fichier officiel jQuery 4.0.0 depuis le réseau de diffusion de contenu, CDN, sans installation de paquet. Les deux exemples, transitions des enfants, éléments dynamiques, clavier et retrait ont été exécutés avec 3.7.1 et 4.0.0.

Alpha utilise .hover(), Beta utilise .on() délégué depuis #cards. Le contenu reste visible ; seul le fond change. Beta reçoit aussi focusin/focusout pour le focus clavier.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Hover events and keyboard focus</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
    button { font: inherit; margin: 6px; }
    .card { display: block; padding: 20px; border: 2px solid teal; background: white; }
    .active { background: #d9f4ef; }
    .card:focus-visible { outline: 3px solid #af5f00; outline-offset: 3px; }
  </style>
</head>
<body>
  <h1>Compare legacy hover and on</h1>
  <button type="button" id="add">Add modern card</button>
  <button type="button" id="bind">Bind modern</button>
  <button type="button" id="unbind">Unbind modern</button>
  <button type="button" id="reset">Reset</button>
  <div id="cards">
    <button type="button" class="card legacy">Legacy <span>Alpha</span></button>
    <button type="button" class="card modern">Modern <span>Beta</span></button>
  </div>
  <p id="result" aria-live="polite"></p>
  <script>
    $(function () {
      const $cards = $("#cards");
      let legacyEntries = 0;
      let modernEntries = 0;
      function report() {
        $("#result").text(`legacy enters=${legacyEntries} | modern enters=${modernEntries}`);
      }
      $(".legacy").hover(function () {
        legacyEntries++;
        $(this).addClass("active");
        report();
      }, function () { $(this).removeClass("active"); });
      function bindModern() {
        $cards.off(".hoverLesson").on(
          "mouseenter.hoverLesson mouseleave.hoverLesson focusin.hoverLesson focusout.hoverLesson",
          ".modern", function (event) {
            const $card = $(this);
            if (event.type === "mouseenter") { $card.data("inside", true); modernEntries++; }
            if (event.type === "mouseleave") $card.data("inside", false);
            if (event.type === "focusin") $card.data("focused", true);
            if (event.type === "focusout") $card.data("focused", false);
            $card.toggleClass("active", Boolean($card.data("inside") || $card.data("focused")));
            report();
          }
        );
      }
      $("#bind").on("click", bindModern);
      $("#unbind").on("click", function () {
        $cards.off(".hoverLesson");
        $(".modern").removeClass("active").removeData("inside focused");
      });
      $("#add").on("click", function () {
        if (!$("#gamma").length) $('<button type="button" id="gamma" class="card modern">Modern <span>Gamma</span></button>').appendTo($cards);
      });
      $("#reset").on("click", function () {
        $("#gamma").remove();
        $(".card").removeClass("active").removeData("inside focused");
        legacyEntries = 0;
        modernEntries = 0;
        bindModern();
        report();
      });
      bindModern();
      report();
    });
  </script>
</body>
</html>

Les deux compteurs d'entrée commencent à zéro :

legacy enters=0 | modern enters=0
  1. Entrez dans Legacy Alpha. Son fond change et legacy enters augmente une fois. Passer sur son span Alpha interne ne l'augmente pas encore.
  2. Sortez pour retirer la mise en évidence. Modern Beta augmente de même modern enters à chaque entrée.
  3. Add modern card crée Gamma. Le gestionnaire délégué du parent traite cette nouvelle carte sans nouvel enregistrement individuel.
  4. Avec Tab, donnez le focus à Beta : fond et contour apparaissent. Sortir seulement le pointeur conserve le fond tant que le focus reste. Il faut que les deux quittent la carte pour le retirer.
  5. Unbind modern désactive uniquement Modern. Le hover d'Alpha fonctionne encore.
  6. Répéter Bind modern ne duplique pas les appels. Reset retire Gamma et les mises en évidence, remet les compteurs à zéro et reconnecte Modern.

inside et focused suivent séparément pointeur et focus. L'un ou l'autre suffit à conserver la mise en évidence. La supprimer sans condition sur mouseleave effacerait l'indication alors que le focus clavier est encore présent.

Éléments dynamiques et portée du retrait

La forme déléguée de .on() s'attache à un parent stable avec un sélecteur de descendants. Ici #cards reste présent et seuls les boutons .modern sont traités. .hover() s'attache directement aux éléments sélectionnés lors de l'enregistrement ; les futurs éléments ne l'héritent pas automatiquement.

hoverLesson est un espace de noms d'événements. bindModern() appelle d'abord .off(".hoverLesson") pour retirer uniquement ses propres gestionnaires avant de les reconnecter. .off() sans argument ou .off("mouseenter mouseleave") trop large pourrait retirer ceux d'autres composants.

Dans une function classique, this est la carte Modern traitée. Il diffère d'event.target, qui peut être le span interne à l'origine de l'événement. Ne remplacez pas cette fonction aveuglément par une fonction fléchée si vous avez besoin de ce this.

Fonction commune et modes d'entrée

Exécutez ce fragment complet dans la Console des outils de développement pour voir une même fonction recevoir les deux types. Il déclenche les événements sur un bouton temporaire non inséré, puis le nettoie. Le déplacement réel du pointeur se vérifie avec l'exemple complet.

const events = [];
const $button = $("<button>Temporary</button>");
$button.hover(function (event) { events.push(event.type); });
$button.trigger("mouseenter").trigger("mouseleave");
console.log(events.join(", "));
$button.remove();
mouseenter, mouseleave

Il s'agit d'entrée et de sortie, pas d'un suivi continu de chaque mouvement. Examiner event.type et définir un état explicite peut éviter qu'un simple toggle soit inversé après d'autres changements d'état.

Sur écran tactile, ne réservez pas l'accès aux contenus essentiels au survol de souris. Prévoyez clic/toucher et clavier pour les fonctions importantes. Pour une simple décoration, CSS :hover et :focus-visible peuvent suffire. Cet exemple affiche toujours le contenu et ne change que sa mise en évidence.