อัปเดตสำหรับ RC.5
ด้วยเชิงมุม 2 เราสามารถใช้ประกอบการ debounce RxJS debounceTime()
ในการควบคุมของฟอร์มvalueChanges
สังเกต:
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 ถามในความคิดเห็นด้านล่าง
แม้ว่ารหัสข้างต้นอาจเป็นวิธีเชิงมุมของการทำมันก็ไม่ได้มีประสิทธิภาพ การกดแป้นทุกครั้งและทุกเหตุการณ์ที่ปรับขนาดแม้ว่าจะถูกคัดออกและควบคุมปริมาณ แต่ส่งผลให้การตรวจจับการเปลี่ยนแปลงทำงานอยู่ ในคำอื่น ๆdebouncing และการควบคุมปริมาณไม่ส่งผลกระทบต่อวิธีการที่มักจะเปลี่ยนการตรวจสอบการทำงาน (ฉันพบความคิดเห็น GitHubโดย Tobias Bosch ที่ยืนยันสิ่งนี้) คุณสามารถเห็นสิ่งนี้เมื่อคุณเรียกใช้ตัวเรียงลำดับและคุณเห็นจำนวนครั้งที่ngDoCheck()
ถูกเรียกเมื่อคุณพิมพ์ลงในกล่องอินพุตหรือปรับขนาดหน้าต่าง (ใช้ปุ่ม "x" สีน้ำเงินเพื่อเรียกใช้งานพลั่วเกอร์ในหน้าต่างแยกต่างหากเพื่อดูเหตุการณ์การปรับขนาด)
เทคนิคที่มีประสิทธิภาพมากขึ้นคือการสร้าง RxJS สังเกตได้จากเหตุการณ์นอก "โซน" ของ Angular วิธีนี้การตรวจจับการเปลี่ยนแปลงจะไม่ถูกเรียกในแต่ละครั้งที่เกิดเหตุการณ์ขึ้น จากนั้นในวิธีการโทรกลับสมัครรับข้อมูลของคุณการตรวจจับการเปลี่ยนแปลงทริกเกอร์ด้วยตนเอง - เช่นคุณควบคุมเมื่อมีการตรวจพบการเปลี่ยนแปลงที่เรียกว่า:
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()
ข้อคิดเห็นใน plunker) โปรดทราบว่าการโทรtick()
จะทำให้ngDoCheck()
ถูกเรียก