web-dev-qa-db-fra.com

angular2: Comment utiliser les observables pour rebondir la fenêtre: redimensionner

donc j'essaie de trouver un moyen de déboucher la fenêtre: redimensionner les événements en utilisant des observables, donc une sorte de fonction ne serait appelée qu'après que l'utilisateur a arrêté la fenêtre de redimensionnement ou qu'un certain temps se soit écoulé sans changement de taille (disons 1sec).

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

est juste un exemple simple qui utilise window: resize et montre qu'il réagit instantanément (utilisez "Lancer l'aperçu dans une fenêtre séparée").

17
LithStud

Je pense que vous ne pouvez pas rebondir de cette façon en utilisant observable. En fait, de telles choses ne sont pas prises en charge dès maintenant, mais il y a un problème ouvert pour cela:

Pour atteindre votre objectif, vous pouvez utiliser directement le Observable.fromEvent pour obtenir un observable pour cet événement. Vous pouvez donc appliquer l'opérateur debounceTime sur cet observable.

Voici un exemple:

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

Voir ce plunkr: https://plnkr.co/edit/uVrRXtnZj8warQ3qUTdN?p=preview

36
Thierry Templier

Dans l'une de nos applications, nous avions également l'implémentation proposée par Thierry Templier, mais j'ai remarqué que la détection de changement d'Angular se déclenche (beaucoup) au redimensionnement de la fenêtre, ce qui rend notre application lente au redimensionnement.

Corrigé en utilisant des zones et un sujet, comme ceci:

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

Voir plunker avec le problème ici (redimensionner l'écran et la console de montre).

Et plunker avec le correctif de ce problème ici (redimensionner l'écran et la console de montre).

11

Vous pouvez utiliser @ HostListener décorateur. Il s'agit d'un moyen courant de souscrire à des événements comme celui-ci.

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

Vous pouvez en savoir plus sur @HostListenerici ou ici .

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