web-dev-qa-db-ja.com

angular2:オブザーバブルを使用してウィンドウをデバウンスする方法:サイズ変更

したがって、オブザーバブルを使用して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を使用し、即座に反応することを示す単純なサンプルです(「別のウィンドウでプレビューを起動」を使用してください)。

17
LithStud

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

36

私たちのアプリの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 (画面のサイズを変更してコンソールを監視する)。

11

@ 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);
  }
}

@HostListenerhere または here の詳細をご覧ください。

7
Londeren
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);
  }
}
1
A. Morel