Comprensión profunda de addEventListener

Sintaxis 1: target.addEventListener(type, listener, useCapture)

Parámetro 1: tipo de evento, como hacer clic, ingresar con el mouse, arrastrar, etc.

Parámetro dos: la función de devolución de llamada cuando se activa el evento.

Parámetro tres: useCaptureEl valor predeterminado es falso, lo que indica que el evento se procesa en la fase de burbujeo. Si es verdadero, el evento se maneja durante la fase de captura.



Sintaxis 2: target.addEventListener(type, listener, options)

objeto de opciones:

useCapture: El valor predeterminado es falso, el evento se activará en la fase de burbujeo. Si es verdadero, el evento se disparará durante la fase de captura.

once: indica si el oyente se invoca como máximo una vez después de agregarlo. Si es verdadero, el oyente se eliminará automáticamente después de que se llame.

passive: Cuando se establece en verdadero, el oyente nunca llamará a preventDefault(). El rendimiento de desplazamiento se puede mejorar mediante el uso pasivo . (De acuerdo con el estándar, el valor de pasivo es falso de forma predeterminada, y las versiones más recientes de Chrome y Firefox han establecido pasivo en verdadero de forma predeterminada).



¿Por qué aparece el pasivo? ? -- addEventListener utiliza pasiva para mejorar el rendimiento de desplazamiento

Algunos eventos en el lado móvil, como touchstart, touchmove, touchend, touchcancel, etc., si el comportamiento predeterminado está bloqueado en estos eventos, se prohibirá el desplazamiento o el zoom de la página.


El navegador no puede saber de antemano si un oyente prohibirá el comportamiento predeterminado y no ejecutará el comportamiento predeterminado hasta que se ejecute el oyente. La ejecución del oyente lleva mucho tiempo. Si tarda 2 segundos antes de event.preventDefault(), esto hará que la página se congele.


Para mejorar la experiencia de desplazamiento en este escenario, necesitamos un parámetro para decirle al navegador que no habrá event.preventDefault() en mi detector de eventos, y puede desplazarse todo lo que quiera sin esperar a que termine el detector. ejecutando Así que hay un atributo pasivo. Para ser compatible con el useCapture anterior, el último parámetro se cambió a opciones de objeto.


Por lo tanto, al enlazar eventos táctiles y de desplazamiento relacionados con el terminal móvil, utilice tanto como sea posible { passive: true }para mejorar el rendimiento y la experiencia y evitar bloqueos de página.


Sin embargo, no todos los navegadores admiten la función pasiva. Los navegadores que no admiten la función pasiva usarán el último parámetro como useCapture, por lo que se necesita este código sutil para determinar si la función pasiva es compatible:

// Test via a getter in the options object to see 
// if the passive property is accessed
var supportsPassive = false;
try {
    
    
  var opts = Object.defineProperty({
    
    }, 'passive', {
    
    
    get: function() {
    
    
      supportsPassive = true;
    }
  });
  window.addEventListener("test", null, opts);
} catch (e) {
    
    }


// Use our detect's results. 
// passive applied if supported, capture will be false either way.
elem.addEventListener(
  'touchstart',
  fn,
  supportsPassive ? {
    
     passive: true } : false
);

Al Object.definePropertyconfigurar un descriptor de acceso de obtención pasivo y agregar un evento de prueba, se llamará al descriptor de acceso de obtención cuando el navegador lo admita, y se establece supportPassive en el descriptor de acceso de obtención.


En el marco Angular, Angular CDK ya se ha proporcionado en @angular/cdk/platformel módulo normalizePassiveListenerOptions({passive: true})para que podamos resolver problemas de compatibilidad. El código central es el siguiente:

/**
 * @license
 * Copyright Google LLC All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */

/** Cached result of whether the user's browser supports passive event listeners. */
let supportsPassiveEvents: boolean;

/**
 * Checks whether the user's browser supports passive event listeners.
 * See: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
 */
export function supportsPassiveEventListeners(): boolean {
    
    
  if (supportsPassiveEvents == null && typeof window !== 'undefined') {
    
    
    try {
    
    
      window.addEventListener(
        'test',
        null!,
        Object.defineProperty({
    
    }, 'passive', {
    
    
          get: () => (supportsPassiveEvents = true),
        }),
      );
   } finally {
    
    
      supportsPassiveEvents = supportsPassiveEvents || false;
    }
  }

  return supportsPassiveEvents;
}

/**
 * Normalizes an `AddEventListener` object to something that can be passed
 * to `addEventListener` on any browser, no matter whether it supports the
 * `options` parameter.
 * @param options Object to be normalized.
 */
export function normalizePassiveListenerOptions(
  options: AddEventListenerOptions,
): AddEventListenerOptions | boolean {
    
    
  return supportsPassiveEventListeners() ? options : !!options.capture;
}

Agregue problemas relacionados para vincular eventos para admitir parámetros pasivos: https://github.com/angular/angular/issues/8866

Supongo que te gusta

Origin blog.csdn.net/Kate_sicheng/article/details/125705487
Recomendado
Clasificación