Angular2: как использовать наблюдаемые для окна debounce: изменить размер
поэтому я пытаюсь выяснить способ дебюта окна: изменить размер событий с помощью наблюдаемых, поэтому некоторая функция будет вызываться только после того, как пользователь остановил окно изменения размера или какое-то время прошло без изменения размера (скажем, 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;
}
}
- просто простой пример, который использует окно: изменение размера и показывает, что он реагирует мгновенно (используйте "Предварительный запуск в отдельном окне" ).
Ответы
Ответ 1
Я думаю, что вы не можете разгадать этот путь с помощью наблюдаемого. На самом деле, такие вещи не поддерживаются прямо сейчас, но для этого есть открытая проблема:
Чтобы достичь своей цели, вы можете напрямую использовать 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
Ответ 2
В одном из наших приложений у нас также была реализация, которую предлагает Thierry Templier, но я заметил, что обнаружение угловых изменений запускает (много) при изменении размера окна, что замедляет изменение нашего приложения при изменении размера.
Исправлено с помощью зоны и темы, например так:
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); });
}
Смотрите plunker с проблемой здесь (измените размер экрана и посмотрите консоль).
И плункер с исправлением этой проблемы здесь (измените размер экрана и посмотрите консоль).
Ответ 3
Вы можете использовать @HostListener decorator. Это распространенный способ подписки на подобные события.
@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);
}
}
Вы можете прочитать больше о @HostListener
здесь или здесь.