RC.5 용으로 업데이트
Angular 2를 사용 debounceTime()
하면 양식 컨트롤의 valueChanges
관찰 가능 항목 에서 RxJS 연산자 를 사용하여 디 바운스 할 수 있습니다 .
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
위의 코드에는 아래 주석에서 @albanx의 요청에 따라 창 크기 조정 이벤트를 조절하는 방법에 대한 예제도 포함되어 있습니다.
위의 코드는 아마도 Angular-way 방식이지만 효율적이지 않습니다. 모든 키 입력 및 크기 조정 이벤트는 디 바운스되고 조절 되더라도 변경 감지가 실행됩니다. 다시 말해, 디 바운싱 및 스로틀 링은 변경 감지 실행 빈도에 영향을 미치지 않습니다 . ( Tobias Bosch 의 GitHub 주석 에서이를 확인했습니다.) 플런저를 실행할 때이 내용을 볼 ngDoCheck()
수 있으며 입력 상자에 입력하거나 창 크기를 조정할 때 호출 횟수를 확인할 수 있습니다. 크기 조정 이벤트를 보려면 파란색 "x"버튼을 사용하여 플런저를 별도의 창에서 실행하십시오.
보다 효율적인 기술은 Angular의 "영역"외부의 이벤트에서 RxJS Observables를 직접 만드는 것입니다. 이렇게하면 이벤트가 발생할 때마다 변경 감지가 호출되지 않습니다. 그런 다음 구독 콜백 메소드에서 수동으로 변경 감지를 트리거하십시오. 즉, 변경 감지가 호출되는시기를 제어합니다.
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
나는 그것을 정의 하기 위해 ngAfterViewInit()
대신에 사용 합니다 .ngOnInit()
inputElRef
detectChanges()
이 구성 요소와 해당 하위 요소에서 변경 감지를 실행합니다. 루트 구성 요소에서 변경 감지를 실행하려면 (즉, 전체 변경 감지 확인을 실행) ApplicationRef.tick()
대신 사용하십시오. ( ApplicationRef.tick()
플 런커의 의견에 전화를 걸었습니다.) 전화 tick()
하면 전화 가 걸립니다 ngDoCheck()
.