RC.5 için güncellendi
Angular 2 debounceTime()ile bir form kontrolünün valueChangesgözlemlenebilir olan RxJS operatörünü kullanarak geri dönebiliriz :
import {Component} from '@angular/core';
import {FormControl} from '@angular/forms';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/throttleTime';
import 'rxjs/add/observable/fromEvent';
@Component({
selector: 'my-app',
template: `<input type=text [value]="firstName" [formControl]="firstNameControl">
<br>{{firstName}}`
})
export class AppComponent {
firstName = 'Name';
firstNameControl = new FormControl();
formCtrlSub: Subscription;
resizeSub: Subscription;
ngOnInit() {
// debounce keystroke events
this.formCtrlSub = this.firstNameControl.valueChanges
.debounceTime(1000)
.subscribe(newValue => this.firstName = newValue);
// throttle resize events
this.resizeSub = Observable.fromEvent(window, 'resize')
.throttleTime(200)
.subscribe(e => {
console.log('resize event', e);
this.firstName += '*'; // change something to show it worked
});
}
ngDoCheck() { console.log('change detection'); }
ngOnDestroy() {
this.formCtrlSub.unsubscribe();
this.resizeSub .unsubscribe();
}
}
Plunker
Yukarıdaki kod ayrıca, aşağıdaki yorumda @albanx tarafından sorulduğu gibi pencere yeniden boyutlandırma olaylarının nasıl kısaltılacağına dair bir örnek de içerir.
Yukarıdaki kod muhtemelen bunu yapmanın Açısal yolu olsa da, verimli değildir. Her tuş vuruşu ve her yeniden boyutlandırma olayı, kaldırılsa ve kısaltılsa bile, değişiklik algılama çalışmasına neden olur. Başka bir deyişle, debouncing ve throttling , değişiklik algılamanın ne sıklıkta çalıştığını etkilemez . ( Tobias Bosch tarafından bunu onaylayan bir GitHub yorumu buldum .) Daldırıcıyı çalıştırdığınızda bunu görebilirsiniz ngDoCheck()ve giriş kutusuna yazdığınızda veya pencereyi yeniden boyutlandırdığınızda kaç kez çağrıldığını görebilirsiniz . (Yeniden boyutlandırma olaylarını görmek için pistonu ayrı bir pencerede çalıştırmak için mavi "x" düğmesini kullanın.)
Daha etkili bir teknik, RxJS Gözlemlenebilirliklerini Angular'ın "bölgesi" dışında, olaylardan yaratmaktır. Bu şekilde, bir olay her tetiklendiğinde değişiklik algılaması çağrılmaz. Ardından, abone geri arama yöntemlerinizde değişiklik algılamayı manuel olarak tetikleyin - yani, değişiklik algılamanın ne zaman çağrıldığını siz kontrol edersiniz:
import {Component, NgZone, ChangeDetectorRef, ApplicationRef,
ViewChild, ElementRef} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/throttleTime';
import 'rxjs/add/observable/fromEvent';
@Component({
selector: 'my-app',
template: `<input #input type=text [value]="firstName">
<br>{{firstName}}`
})
export class AppComponent {
firstName = 'Name';
keyupSub: Subscription;
resizeSub: Subscription;
@ViewChild('input') inputElRef: ElementRef;
constructor(private ngzone: NgZone, private cdref: ChangeDetectorRef,
private appref: ApplicationRef) {}
ngAfterViewInit() {
this.ngzone.runOutsideAngular( () => {
this.keyupSub = Observable.fromEvent(this.inputElRef.nativeElement, 'keyup')
.debounceTime(1000)
.subscribe(keyboardEvent => {
this.firstName = keyboardEvent.target.value;
this.cdref.detectChanges();
});
this.resizeSub = Observable.fromEvent(window, 'resize')
.throttleTime(200)
.subscribe(e => {
console.log('resize event', e);
this.firstName += '*'; // change something to show it worked
this.cdref.detectChanges();
});
});
}
ngDoCheck() { console.log('cd'); }
ngOnDestroy() {
this.keyupSub .unsubscribe();
this.resizeSub.unsubscribe();
}
}
Plunker
Kullandığım ngAfterViewInit()yerine ngOnInit()sağlamak için inputElReftanımlanır.
detectChanges()bu bileşen ve alt bileşenleri üzerinde değişiklik algılaması yapacaktır. Kök bileĢeninden değiĢiklik algılamasını çalıĢtırmayı tercih ediyorsanız (yani, tam değiĢiklik algılaması denetimi yapın), ApplicationRef.tick()bunun yerine kullanın. ( ApplicationRef.tick()Pistondaki yorumlara bir çağrı koydum.) Çağrı yapılmasının tick()neden olacağını unutmayın ngDoCheck().