したがって、オブザーバブルを使用してwindow:resizeイベントをデバウンスする方法を見つけようとしているため、ユーザーがウィンドウのサイズ変更を停止した後、またはサイズを変更せずに時間が経過した後にのみ、ある種の関数が呼び出されます(たとえば1秒)。
https://plnkr.co/edit/cGA97v08rpc7lAgitCOd
import {Component} from '@angular/core'
@Component({
selector: 'my-app',
providers: [],
template: `
<div (window:resize)="doSmth($event)">
<h2>Resize window to get number: {{size}}</h2>
</div>
`,
directives: []
})
export class App {
size: number;
constructor() {
}
doSmth(e: Event) {
this.size = e.target.innerWidth;
}
}
window:resizeを使用し、即座に反応することを示す単純なサンプルです(「別のウィンドウでプレビューを起動」を使用してください)。
Observableを使用してこの方法でデバウンスすることはできないと思います。実際、そのようなことは、現時点ではサポートされていませんが、これには未解決の問題があります。
目標を達成するために、直接Observable.fromEvent
このイベントのオブザーバブルを取得します。したがって、このオブザーバブルにdebounceTime
演算子を適用できます。
ここにサンプルがあります:
@Component({
(...)
})
export class App {
size: number;
constructor() {
Observable.fromEvent(window, 'resize')
.debounceTime(1500)
.subscribe((event) => {
this.doSmth(event);
});
}
doSmth(e: Event) {
console.log('do smth');
this.size = e.target.innerWidth;
}
}
このplunkrを参照してください: https://plnkr.co/edit/uVrRXtnZj8warQ3qUTdN?p=preview
私たちのアプリの1つで、ティエリーテンプリエが提案する実装もありましたが、Angularの変更検出がウィンドウのサイズ変更時に(大量に)実行され、アプリのサイズ変更が遅くなることに気付きました。
次のようにゾーンと件名を使用して修正しました。
private changeSubject = new Subject<number>();
constructor(private zone: NgZone) {
this.zone.runOutsideAngular(() => {
Observable.fromEvent(window, 'resize')
.debounceTime(1500).distinctUntilChanged().subscribe((e: Event) => {
this.zone.run(() => {
this.changeSubject.next(e);
})
}
)
});
this.changeSubject.subscribe((e: Event) => { this.doSmth(e); });
}
問題のあるプランカーをご覧ください here (画面のサイズを変更してコンソールを監視します)。
そして、この問題を修正したプランカー here (画面のサイズを変更してコンソールを監視する)。
@ HostListener デコレータを使用できます。これは、このようなイベントをサブスクライブする一般的な方法です。
@Component({
// ...
})
export class App {
private changeSize = new Subject();
constructor() {
this.changeSize
.asObservable()
.pipe(
throttleTime(1000)
)
.subscribe(innerWidth => console.log('innerWidth:', innerWidth));
}
@HostListener('window:resize', ['$event.target'])
public onResize(target) {
this.changeSize.next(target.innerWidth);
}
}
import { Component, OnInit, HostListener } from '@angular/core';
import { Subject } from 'rxjs';
import 'rxjs/add/operator/debounceTime';
@Component({
// ...
})
export class App implements OnInit {
resize$ = new Subject<void>();
ngOnInit() {
this.resize$.debounceTime(300).subscribe(
innerWidth => console.log('innerWidth:', innerWidth)
);
}
@HostListener('window:resize', ['$event.target'])
onResize(target) {
this.resize$.next(target.innerWidth);
}
}