2017-06-13 78 views
5

我似乎無法捕捉到窗口滾動事件。在角4.2.2經常如何處理Angular 4中的窗口滾動事件?

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

的片斷來自第2版。這似乎不工作(再): 在幾個網站,我發現類似這樣的代碼。如果我用「window:touchmove」替換「window:scroll」,然後touchmove事件處理正常。

有誰知道我錯過了什麼?非常感謝你!

回答

14

也許你的document不滾動,但它內部是div。如果從document調用該滾動事件,則該滾動事件僅起泡至window。另外,如果您從document中捕獲事件並撥打stopPropagation之類的東西,則您將不會收到window中的事件。

如果你想捕捉你的應用程序內的所有滾動事件,這也將是從微小的滾動容器,你必須使用默認的addEventListeneruseCapture設置爲true

這會在事件發生時觸發DOM而不是泡泡階段。不幸的是,很坦率地說大小姐,角度不提供一個選項,在事件監聽器選項傳遞,所以你必須使用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 
    }; 

} 

現在,這是不是所有有它,因爲所有的主要的瀏覽器(IE和Edge除外)已經實現了新的addEventListener規範,這使得可以傳遞一個對象爲third parameter

使用此對象可以將事件偵聽器標記爲passive。這是一個推薦的事情,這個事件會觸發很多時間,這會干擾UI性能,例如滾動事件。要實現這一點,你應該首先檢查當前瀏覽器是否支持這個功能。在mozilla.org上,他們發佈了一個方法passiveSupported,您可以使用它來檢查瀏覽器支持。你只能使用這個,當你確定你不打算使用event.preventDefault()

在我告訴你如何做到這一點之前,還有另一個你可以想到的性能特徵。爲防止運行中發生變化檢測(每次在區域內發生異步事件時都會調用DoCheck,就像事件觸發一樣),您應該在區域外運行事件偵聽器,並且只有在真正有必要時纔會輸入事件偵聽器。所以,讓我們結合所有這些東西:

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

非常感謝你,這似乎按預期工作!我認爲這個問題的確是文件本身不會在我的情況下滾動。 – Robert

+1

@Robert我已經用更多信息更新了我的答案:) – PierreDuc

+0

第二個代碼塊中的偵聽器中的內容是否與攔截事件相關?此外,如何確定滾動的方向? –