也許你的document
不滾動,但它內部是div
。如果從document
調用該滾動事件,則該滾動事件僅起泡至window
。另外,如果您從document
中捕獲事件並撥打stopPropagation
之類的東西,則您將不會收到window
中的事件。
如果你想捕捉你的應用程序內的所有滾動事件,這也將是從微小的滾動容器,你必須使用默認的addEventListener
法useCapture
設置爲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();
});
}
};
}
非常感謝你,這似乎按預期工作!我認爲這個問題的確是文件本身不會在我的情況下滾動。 – Robert
@Robert我已經用更多信息更新了我的答案:) – PierreDuc
第二個代碼塊中的偵聽器中的內容是否與攔截事件相關?此外,如何確定滾動的方向? –