Para melhorar o desempenho de rolagem/zoom do wheel
, recomendamos que os desenvolvedores
registrem listeners de eventos wheel
e mousewheel
como passivos
transmitindo a opção {passive: true}
para addEventListener()
. O registro
dos listeners de eventos como passivos informa ao navegador que os listeners de roda não
vão chamar preventDefault()
, e o navegador pode rolar e
fazer zoom com segurança sem bloquear os listeners.
O problema é que, na maioria das vezes, os listeners de eventos de roda são conceitualmente
passivos (não chamam preventDefault()
), mas não são especificados explicitamente como
tais, exigindo que o navegador aguarde a conclusão do processamento de eventos do JS antes
de começar a rolar/fazer zoom, mesmo que a espera não seja necessária. No Chrome 56,
resolvemos esse problema para touchstart
e touchmove
,
e essa mudança foi adotada mais tarde pelo Safari e pelo Firefox. Como você pode ver
no vídeo de demonstração que fizemos na época, deixar o comportamento como
ele era produziu um atraso perceptível na resposta de rolagem. Agora, no Chrome 73, aplicamos
a mesma intervenção aos eventos wheel
e mousewheel
.
A intervenção
Nosso objetivo com essa mudança é reduzir o tempo necessário para atualizar a tela
depois que o usuário começa a rolar a roda ou o touchpad sem que os desenvolvedores precisem
mudar o código. Nossas métricas mostram que 75% dos listeners de eventos wheel
e mousewheel
registrados em destinos raiz (janela, documento ou corpo) não
especificam nenhum valor para a opção passiva, e mais de 98% desses
listeners não chamam preventDefault()
. No Chrome 73, estamos mudando os
listeners wheel
e mousewheel
registrados em destinos raiz (janela,
documento ou corpo) para serem passivos por padrão. Isso significa que um listener de eventos
como:
window.addEventListener("wheel", func);
fica equivalente a:
window.addEventListener("wheel", func, {passive: true});
E a chamada de preventDefault()
dentro do listener será ignorada com o
seguinte aviso do DevTools:
[Intervention] Unable to preventDefault inside passive event listener due
to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312
Interrupção e orientação
Na grande maioria dos casos, não há quebra. Somente em casos raros
(menos de 0,3% das páginas de acordo com nossas métricas), a rolagem/zoom não intencionais
podem acontecer devido à chamada preventDefault()
ser ignorada dentro dos
listeners que são tratados como passivos por padrão. Seu app pode
determinar se ele pode estar atingindo esse ponto verificando se a chamada
preventDefault()
teve algum efeito pela propriedade defaultPrevented
. A correção
para os casos afetados é relativamente fácil: transmita {passive: false}
para
addEventListener()
para substituir o comportamento padrão e preservar o listener
de eventos como bloqueio.