Aby poprawić działanie przewijania i powiększania wheel
, zalecamy rejestrowanie detektorów zdarzeń wheel
i mousewheel
jako pasywnych, podając opcję {passive: true}
jako addEventListener()
. Rejestrowanie detektorów zdarzeń jako pasywnych informuje przeglądarkę, że detektory koła nie będą wywoływać metody preventDefault()
, a przeglądarka może bezpiecznie przewijać i powiększać bez blokowania detektorów.
Problem polega na tym, że przetwarzanie zdarzeń związanych z kołem jest najczęściej w koncepcji pasywne (nie wywołuje funkcji preventDefault()
), ale nie jest wyraźnie tak określone, co powoduje, że przeglądarka musi czekać na zakończenie przetwarzania zdarzenia JS, zanim zacznie przewijać lub powiększać obraz, mimo że oczekiwanie nie jest konieczne. W Chrome 56 poprawiliśmy ten błąd w przypadku touchstart
i touchmove
, a ta zmiana została później zaadaptowana przez Safari i Firefox. Jak widać na filmie demonstracyjnym, który nagraliśmy w tamtym czasie, zachowanie pozostawione bez zmian spowodowało zauważalne opóźnienie w reakcji na przewijanie. W Chrome 73 zastosowaliśmy te same środki zaradcze do zdarzeń wheel
i mousewheel
.
Interwencja
Celem tej zmiany jest skrócenie czasu potrzebnego na aktualizację wyświetlacza po rozpoczęciu przewijania za pomocą kółka lub touchpada, bez konieczności zmiany kodu. Nasze dane wskazują, że 75% wydarzeń wheel
i mousewheel
zarejestrowanych na korzeniach obiektów docelowych (window, document lub body) nie określa żadnych wartości dla opcji passive, a ponad 98% takich uchwytów nie wywołuje metody preventDefault()
. W Chrome 73 zmieniamy tak, aby komponenty wheel
i mousewheel
zarejestrowane na elementach korzenia (okno, dokument lub body) były domyślnie pasywne. Oznacza to, że detektor zdarzeń:
window.addEventListener("wheel", func);
staje się równoważny następującemu wyrażeniu:
window.addEventListener("wheel", func, {passive: true});
Wywołanie preventDefault()
w słuchaczu zostanie zignorowane, a w Narzędziach deweloperskich pojawi się to ostrzeżenie:
[Intervention] Unable to preventDefault inside passive event listener due
to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312
Uszkodzenia i wskazówki
W większości przypadków nie dochodzi do żadnych naruszeń. Tylko w rzadkich przypadkach (według naszych danych mniej niż 0,3% stron) może wystąpić niezamierzone przewijanie lub powiększanie, ponieważ wywołanie preventDefault()
jest ignorowane w słuchaczach, które są domyślnie traktowane jako pasywne. Aplikacja może określić, czy jest to problem występujący w naturze, sprawdzając, czy wywołanie funkcji preventDefault()
miało jakikolwiek wpływ na usługę defaultPrevented
. Rozwiązanie problemu w przypadku dotkniętych przypadków jest stosunkowo proste: prześlij {passive: false}
do addEventListener()
, aby zastąpić domyślne działanie i zachować blokowanie przez listenera zdarzeń.