angular2:如何使用 observables 去抖 window:resize
angular2: How to use observables to debounce window:resize
所以我想找出一种方法来使用可观察对象去除 window:resize 事件,因此只有在用户停止调整大小 window 或一段时间后没有大小的情况下才会调用某种函数变化(比如 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 并表明它会立即做出反应(使用 "Launch preview in separate window")。
我认为您不能使用 observable 以这种方式去抖动。事实上,现在不支持开箱即用的东西,但有一个未解决的问题:
为了实现您的目标,您可以直接使用 Observable.fromEvent
来获取此事件的可观察值。所以你可以在这个 observable 上应用 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
在我们的一个应用程序中,我们也有 Thierry Templier 建议的实现,但我注意到 Angular 的变化检测在 window 调整大小时触发(很多),这使得我们的应用程序调整大小慢。
通过使用区域和主题修复它,如下所示:
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 问题 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);
}
}
所以我想找出一种方法来使用可观察对象去除 window:resize 事件,因此只有在用户停止调整大小 window 或一段时间后没有大小的情况下才会调用某种函数变化(比如 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 并表明它会立即做出反应(使用 "Launch preview in separate window")。
我认为您不能使用 observable 以这种方式去抖动。事实上,现在不支持开箱即用的东西,但有一个未解决的问题:
为了实现您的目标,您可以直接使用 Observable.fromEvent
来获取此事件的可观察值。所以你可以在这个 observable 上应用 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
在我们的一个应用程序中,我们也有 Thierry Templier 建议的实现,但我注意到 Angular 的变化检测在 window 调整大小时触发(很多),这使得我们的应用程序调整大小慢。
通过使用区域和主题修复它,如下所示:
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 问题 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);
}
}