ウィンドウスクロールイベントをキャプチャできないようです。いくつかのサイトで、次のようなコードを見つけました。
@HostListener("window:scroll", [])
onWindowScroll() {
console.log("Scrolling!");
}
スニペットは多くの場合バージョン2からのものです。これはAngular 4.2.2では機能していないようです(もう?)。たとえば、「window:scroll」を「window:touchmove」に置き換えた場合、touchmoveイベントは正常に処理されます。
誰かが私が欠けていることを知っていますか?どうもありがとうございました!
おそらくあなたのdocument
はスクロールしていませんが、その中のdiv
はスクロールしています。スクロールイベントは、window
から呼び出された場合にのみdocument
までバブルします。また、document
からイベントをキャプチャし、stopPropagation
のようなものを呼び出した場合、window
でイベントを受信しません。
アプリケーション内のすべてのスクロールイベントをキャプチャする場合は、これも小さなスクロール可能なコンテナからのものであり、addEventListener
をuseCapture
に設定したデフォルトのtrue
メソッドを使用する必要があります。
これにより、バブルステージではなくDOM
を下るときにイベントが発生します。残念ながら、率直に言って大きなミスです。angularはイベントリスナーオプションを渡すオプションを提供しないため、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
仕様を実装しているため、これですべてではありません。これにより、オブジェクトを次のように渡すことができます。 番目のパラメーター 。
このオブジェクトを使用すると、イベントリスナーを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();
});
}
};
}
たまたまAngular Materialを使用:
import { ScrollDispatchModule } from '@angular/cdk/scrolling';
Tsで:
import { ScrollDispatcher } from '@angular/cdk/scrolling';
constructor(private scrollDispatcher: ScrollDispatcher) {
this.scrollDispatcher.scrolled().subscribe(x => console.log('I am scrolling'));
}
そしてテンプレートで:
<div cdkScrollable>
<div *ngFor="let one of manyToScrollThru">
{{one}}
</div>
</div>
まだコメントできません。 @PierreDucは、ドキュメントがスクロールしないと@Robertが言った場合を除いて、あなたの答えがスポットにあります。リスナーから送信されたイベントを使用してソース要素を監視するように、回答を少し変更しました。
ngOnInit() {
window.addEventListener('scroll', this.scrollEvent, true);
}
ngOnDestroy() {
window.removeEventListener('scroll', this.scrollEvent, true);
}
scrollEvent = (event: any): void => {
const number = event.srcElement.scrollTop;
}
@PierreDuc、答えてくれてありがとう。
パッシブリスナーによるスクロールパフォーマンスの向上 MDNのセクションで説明されているとおり:
基本的なscrollイベントのpassiveの値について心配する必要はありません。キャンセルできないため、イベントリスナーはページのレンダリングをブロックできません。
したがって、私に関する限り、window.addEventListener関数の3番目のパラメーターとしてtrueを渡すだけで、答えを単純化できます。