Pour améliorer les performances de défilement/zoom de wheel
, les développeurs sont invités à enregistrer les écouteurs d'événements wheel
et mousewheel
comme passifs en transmettant l'option {passive: true}
à addEventListener()
. Enregistrer les écouteurs d'événements en tant que passifs indique au navigateur que les écouteurs de la roue ne vont pas appeler preventDefault()
et que le navigateur peut effectuer le défilement et le zoom en toute sécurité sans bloquer les écouteurs.
Le problème est que, le plus souvent, les écouteurs d'événements de la roue sont conceptuellement passifs (n'appellent pas preventDefault()
), mais ne sont pas explicitement spécifiés en tant que tels, ce qui oblige le navigateur à attendre la fin de la gestion des événements JavaScript avant de commencer à faire défiler/zoomer, même si l'attente n'est pas nécessaire. Dans Chrome 56, nous avons corrigé ce problème pour touchstart
et touchmove
. Ce changement a ensuite été adopté par Safari et Firefox. Comme vous pouvez le voir dans la vidéo de démonstration que nous avons réalisée à l'époque, laisser le comportement tel quel a entraîné un délai notable dans la réponse au défilement. Dans Chrome 73, nous avons appliqué la même intervention aux événements wheel
et mousewheel
.
The Intervention
Notre objectif avec cette modification est de réduire le temps nécessaire pour mettre à jour l'écran une fois que l'utilisateur commence à faire défiler l'écran à l'aide de la molette ou du pavé tactile, sans que les développeurs aient à modifier le code. Nos métriques montrent que 75% des écouteurs d'événements wheel
et mousewheel
enregistrés sur des cibles racine (fenêtre, document ou corps) ne spécifient aucune valeur pour l'option passive et que plus de 98% de ces écouteurs n'appellent pas preventDefault()
. Dans Chrome 73, nous faisons en sorte que les écouteurs wheel
et mousewheel
enregistrés sur les cibles racine (fenêtre, document ou corps) soient passifs par défaut. Cela signifie qu'un écouteur d'événements comme:
window.addEventListener("wheel", func);
devient équivalent à:
window.addEventListener("wheel", func, {passive: true});
L'appel de preventDefault()
dans l'écouteur sera ignoré avec l'avertissement DevTools suivant:
[Intervention] Unable to preventDefault inside passive event listener due
to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312
Défaillances et conseils
Dans la grande majorité des cas, aucune rupture n'est observée. Dans de rares cas (moins de 0,3% des pages selon nos métriques), un défilement/un zoom involontaire peut se produire en raison de l'appel preventDefault()
ignoré dans les écouteurs traités comme passifs par défaut. Votre application peut déterminer si elle peut rencontrer ce problème dans la pratique en vérifiant si l'appel de preventDefault()
a eu un effet via la propriété defaultPrevented
. La correction des cas concernés est relativement simple: transmettez {passive: false}
à addEventListener()
pour remplacer le comportement par défaut et conserver l'écouteur d'événements en tant que blocage.