2017-06-13 20 views
5

Nie mogę uchwycić zdarzenia przewijania okna. W kilku miejscach znalazłem kodu podobnego do tego:Jak obsługiwać zdarzenie przewijania okna w Angular 4?

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

Fragmenty często pochodzą z wersji 2. To nie wydają się działać (?) Już w Kątowymi 4.2.2. Jeśli na przykład zamieniam "okno: przewiń" na "okno: touchmove", wówczas dotykowy event będzie obsługiwany poprawnie.

Czy ktoś wie, czego mi brakuje? Dziękuję Ci bardzo!

Odpowiedz

14

Prawdopodobnie twój document nie przewija się, ale jest w nim div. Zdarzenie przewijania tylko bąble do window, jeśli jest wywoływane z document. Jeśli przechwycisz zdarzenie z document i wywołasz coś podobnego do stopPropagation, nie otrzymasz tego zdarzenia w window.

Jeśli chcesz przechwytywać wszystkie zdarzenia przewijania wewnątrz aplikacji, które będą również z malutkich przewijalnych pojemników, trzeba użyć metody domyślnej addEventListener z useCapture zestaw do true.

Spowoduje to wywołanie zdarzenia, gdy przejdzie ono w dół DOM, zamiast etapu bubble. Niestety, i szczerze mówiąc wielka miss, kanciasty nie przewiduje opcję przejść w opcjach detektora zdarzeń, więc trzeba użyć 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 
    }; 

} 

Teraz to nie jest wszystko, co trzeba, bo wszystko główne przeglądarki (z wyjątkiem oczywiście IE i Edge) zaimplementowały nową specyfikację addEventListener, która umożliwia przekazanie obiektu jako third parameter.

Za pomocą tego obiektu można oznaczyć detektor zdarzeń jako passive. Jest to zalecana czynność związana z wydarzeniem, które wystrzeliwuje dużo czasu, co może zakłócać działanie interfejsu użytkownika, na przykład zdarzenia przewijania. Aby to zaimplementować, najpierw sprawdź, czy bieżąca przeglądarka obsługuje tę funkcję. Na mozilla.org umieścili metodę passiveSupported, dzięki której można sprawdzić obsługę przeglądarki. Możesz tego używać tylko wtedy, gdy masz pewność, że nie zamierzasz używać tej metody, zanim możesz pokazać, jak to zrobić. Aby uniemożliwić wykrywanie zmian (wywołanie DoCheck jest wywoływane za każdym razem, gdy coś się dzieje w strefie, podobnie jak w przypadku wystrzeliwania zdarzenia), należy uruchomić odbiornik zdarzeń poza strefą i wprowadzić go tylko wtedy, gdy jest to naprawdę konieczne. Soo, połączmy wszystkie te rzeczy:

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(); 
      }); 
     } 
    }; 
} 
+0

Bardzo dziękuję, wydaje się działać zgodnie z oczekiwaniami! Myślę, że problem polega na tym, że sam dokument nie przewija się w mojej sytuacji. – Robert

+1

@Robert Zaktualizowałem swoją odpowiedź nieco bardziej z dodatkowymi informacjami :) – PierreDuc

+0

Czy treść w odbiorniku w drugim bloku kodu jest skorelowana z przechwytywaniem zdarzeń? Co więcej, jak powinien wyglądać kierunek przewijania? –

Powiązane problemy