way two data angular typescript scroll

two - ¿Cómo manejar el evento de desplazamiento de ventana en Angular 4?



get element angular 6 (4)

Parece que no puedo capturar el evento de desplazamiento de la ventana. En varios sitios encontré un código similar a este:

@HostListener("window:scroll", []) onWindowScroll() { console.log("Scrolling!"); }

Los fragmentos a menudo provienen de la versión 2. Esto parece no funcionar (¿ya?) En Angular 4.2.2. Si reemplazo "window: scroll" con "window: touchmove", por ejemplo, entonces el evento touchmove se maneja bien.

¿Alguien sabe lo que me estoy perdiendo? ¡Muchas gracias!


@PierreDuc gracias por la respuesta.

Como se describe en la sección Mejora del rendimiento de desplazamiento con oyentes pasivos en MDN:

No necesita preocuparse por el valor de pasivo para el evento de desplazamiento básico. Como no se puede cancelar, los oyentes de eventos no pueden bloquear la representación de la página de todos modos.

Por lo que a mí respecta, su respuesta puede simplificarse simplemente pasando true como el tercer parámetro para la función window.addEventListener


No tengo permitido comentar todavía. @PierreDuc su respuesta es acertada, excepto cuando @Robert dijo que el documento no se desplaza. Modifiqué un poco su respuesta para usar el evento enviado por el oyente y luego monitorear el elemento fuente.

ngOnInit() { window.addEventListener(''scroll'', this.scrollEvent, true); } ngOnDestroy() { window.removeEventListener(''scroll'', this.scrollEvent, true); } scrollEvent = (event: any): void => { const number = event.srcElement.scrollTop; }


Probablemente su document no se esté desplazando, pero sí un div dentro. El evento de desplazamiento solo aparece en la window si se llama desde el document . Además, si captura el evento del document y llama a algo como stopPropagation , no recibirá el evento en la window .

Si desea capturar todos los eventos de desplazamiento dentro de su aplicación, que también serán de pequeños contenedores desplazables, debe usar el método addEventListener predeterminado con useCapture establecido en true .

Esto activará el evento cuando baje el DOM , en lugar de la etapa de burbuja. Desafortunadamente, y francamente una gran falta, angular no proporciona una opción para pasar las opciones de escucha del evento, por lo que debe usar addEventListener :

export class WindowScrollDirective { ngOnInit() { window.addEventListener(''scroll'', this.scroll, true); //third parameter } ngOnDestroy() { window.removeEventListener(''scroll'', this.scroll, true); } scroll = (): void => { //handle your scroll here //notice the ''odd'' function assignment to a class field //this is used to be able to remove the event listener }; }

Ahora, esto no es todo, ya que todos los principales navegadores (excepto IE y Edge, obviamente) han implementado la nueva especificación addEventListener , que permite pasar un objeto como tercer parámetro .

Con este objeto puede marcar un detector de eventos como passive . Se recomienda hacer esto en un evento que se activa mucho tiempo, lo que puede interferir con el rendimiento de la interfaz de usuario, como el evento de desplazamiento. Para implementar esto, primero debe verificar si el navegador actual admite esta función. En mozilla.org, han publicado un método passiveSupported , con el que puede verificar la compatibilidad del navegador. Sin embargo, solo puede usar esto cuando esté seguro de que no va a usar event.preventDefault()

Antes de mostrarle cómo hacerlo, hay otra característica de rendimiento que se le ocurre. Para evitar que se ejecute la detección de cambios (se llama a DoCheck cada vez que ocurre algo asíncrono dentro de la zona. Como un disparo de evento), debe ejecutar su detector de eventos fuera de la zona y solo ingresarlo cuando sea realmente necesario. Entonces, combinemos todas estas cosas:

export class WindowScrollDirective { private eventOptions: boolean|{capture?: boolean, passive?: boolean}; constructor(private ngZone: NgZone) {} ngOnInit() { if (passiveSupported()) { //use the implementation on mozilla this._eventOptions = { capture: true, passive: true }; } else { this.eventOptions = true; } this.ngZone.runOutsideAngular(() => { window.addEventListener(''scroll'', this.scroll, <any>this.eventOptions); }); } ngOnDestroy() { window.removeEventListener(''scroll'', this.scroll, <any>this.eventOptions); //unfortunately the compiler doesn''t know yet about this object, so cast to any } scroll = (): void => { if (somethingMajorHasHappenedTimeToTellAngular) { this.ngZone.run(() => { this.tellAngular(); }); } }; }


Si está utilizando material angular , puede hacer esto:

import { ScrollDispatchModule } from ''@angular/cdk/scrolling'';

En ts:

import { ScrollDispatcher } from ''@angular/cdk/scrolling''; constructor(private scrollDispatcher: ScrollDispatcher) { this.scrollDispatcher.scrolled().subscribe(x => console.log(''I am scrolling'')); }

Y en plantilla:

<div cdkScrollable> <div *ngFor="let one of manyToScrollThru"> {{one}} </div> </div>

Referencia: https://material.angular.io/cdk/scrolling/overview