ใน AngularJS คุณก็สามารถที่จะระบุดูจะสังเกตเห็นการเปลี่ยนแปลงในตัวแปรขอบเขตการใช้ฟังก์ชั่นของ$watch
$scope
อะไรคือสิ่งที่เทียบเท่ากับการเฝ้าดูการเปลี่ยนแปลงของตัวแปร (ในตัวอย่างเช่นตัวแปรองค์ประกอบ) ในเชิงมุม?
ใน AngularJS คุณก็สามารถที่จะระบุดูจะสังเกตเห็นการเปลี่ยนแปลงในตัวแปรขอบเขตการใช้ฟังก์ชั่นของ$watch
$scope
อะไรคือสิ่งที่เทียบเท่ากับการเฝ้าดูการเปลี่ยนแปลงของตัวแปร (ในตัวอย่างเช่นตัวแปรองค์ประกอบ) ในเชิงมุม?
คำตอบ:
ใน Angular 2 การตรวจจับการเปลี่ยนแปลงนั้นเป็นไปโดยอัตโนมัติ ... $scope.$watch()
และ$scope.$digest()
RIP
น่าเสียดายที่ส่วนการตรวจจับการเปลี่ยนแปลงของคู่มือ dev ยังไม่ได้เขียน (มีตัวยึดใกล้ด้านล่างของหน้าภาพรวมสถาปัตยกรรมในส่วน "สิ่งอื่น ๆ ")
นี่คือความเข้าใจของฉันว่าการตรวจจับการเปลี่ยนแปลงทำงานอย่างไร
setTimeout()
ภายในส่วนประกอบของเรามากกว่าที่จะเป็น$timeout
... เพราะsetTimeout()
มีการปะติดลิงChangeDetectorRef
) อุปกรณ์ตรวจจับการเปลี่ยนแปลงเหล่านี้จะถูกสร้างขึ้นเมื่อ Angular สร้างส่วนประกอบ พวกเขาติดตามสถานะของการผูกทั้งหมดของคุณเพื่อตรวจสอบสกปรก ในแง่นี้คล้ายกับอัตโนมัติ$watches()
ที่ Angular 1 จะตั้งค่าสำหรับ{{}}
การผูกแม่แบบ onPush
กลยุทธ์การตรวจจับการเปลี่ยนแปลงกับองค์ประกอบใด ๆ ของคุณ) ทุกองค์ประกอบในแผนผังจะถูกตรวจสอบหนึ่งครั้ง (TTL = 1) ... จากด้านบนตามลำดับความลึกแรก (ถ้าคุณอยู่ในโหมด dev การตรวจจับการเปลี่ยนแปลงจะทำงานสองครั้ง (TTL = 2) ดูApplicationRef.tick ()เพื่อดูข้อมูลเพิ่มเติม) ทำการตรวจสอบสิ่งสกปรกบนการเชื่อมโยงทั้งหมดโดยใช้วัตถุตัวตรวจจับการเปลี่ยนแปลงเหล่านั้น
ngOnChanges()
ไปใช้เพื่อรับการแจ้งเตือนการเปลี่ยนแปลง ngDoCheck()
(ดูคำตอบ SO นี้เพิ่มเติม บนนี้) การอ้างอิงอื่น ๆ เพื่อเรียนรู้เพิ่มเติม:
onPush
นอกจากนี้เขายังพูดถึงเกี่ยวกับการตรวจสอบการเปลี่ยนแปลงในทั่วไปและเล็กน้อยเกี่ยวกับhost
เอกสาร "ฟังพิธีกร" ในAPI doc มันอธิบายวิธีการฟังเหตุการณ์ระดับโลกจากภายในโซนเชิงมุม (ดังนั้นการตรวจจับการเปลี่ยนแปลงจะถูกเรียกตามที่ต้องการ) คำตอบนี้มีพลั่วเกอร์ทำงานอยู่
พฤติกรรมนี้ตอนนี้เป็นส่วนหนึ่งของวงจรชีวิตของส่วนประกอบ
ส่วนประกอบสามารถใช้วิธี ngOnChanges ในอินเทอร์เฟซOnChangesเพื่อเข้าถึงการเปลี่ยนแปลงอินพุต
ตัวอย่าง:
import {Component, Input, OnChanges} from 'angular2/core';
@Component({
selector: 'hero-comp',
templateUrl: 'app/components/hero-comp/hero-comp.html',
styleUrls: ['app/components/hero-comp/hero-comp.css'],
providers: [],
directives: [],
pipes: [],
inputs:['hero', 'real']
})
export class HeroComp implements OnChanges{
@Input() hero:Hero;
@Input() real:string;
constructor() {
}
ngOnChanges(changes) {
console.log(changes);
}
}
หากนอกเหนือไปจากการผูกสองทางอัตโนมัติคุณต้องการเรียกใช้ฟังก์ชันเมื่อมีการเปลี่ยนแปลงค่าคุณสามารถทำลายไวยากรณ์ทางลัดการผูกมัดแบบสองทางเป็นรุ่น verbose เพิ่มเติม
<input [(ngModel)]="yourVar"></input>
เป็นการจดชวเลข
<input [ngModel]="yourVar" (ngModelChange)="yourVar=$event"></input>
(ดูเช่นhttp://victorsavkin.com/post/119943127151/angular-2-template-syntax )
คุณสามารถทำสิ่งนี้:
<input [(ngModel)]="yourVar" (ngModelChange)="changedExtraHandler($event)"></input>
คุณสามารถใช้getter function
หรือget accessor
เพื่อทำหน้าที่เฝ้าดูในเชิงมุม 2
import {Component} from 'angular2/core';
@Component({
// Declare the tag name in index.html to where the component attaches
selector: 'hello-world',
// Location of the template for this component
template: `
<button (click)="OnPushArray1()">Push 1</button>
<div>
I'm array 1 {{ array1 | json }}
</div>
<button (click)="OnPushArray2()">Push 2</button>
<div>
I'm array 2 {{ array2 | json }}
</div>
I'm concatenated {{ concatenatedArray | json }}
<div>
I'm length of two arrays {{ arrayLength | json }}
</div>`
})
export class HelloWorld {
array1: any[] = [];
array2: any[] = [];
get concatenatedArray(): any[] {
return this.array1.concat(this.array2);
}
get arrayLength(): number {
return this.concatenatedArray.length;
}
OnPushArray1() {
this.array1.push(this.array1.length);
}
OnPushArray2() {
this.array2.push(this.array2.length);
}
}
นี่เป็นอีกวิธีใช้ฟังก์ชั่น getter และ setter สำหรับโมเดล
@Component({
selector: 'input-language',
template: `
…
<input
type="text"
placeholder="Language"
[(ngModel)]="query"
/>
`,
})
export class InputLanguageComponent {
set query(value) {
this._query = value;
console.log('query set to :', value)
}
get query() {
return this._query;
}
}
(change)
ตัวจัดการ (s) ลงในทุก ๆ รายการ ฉันไม่ต้องการเพิ่มget|sets
สถานที่ให้บริการในแบบจำลองของฉันทุกคน มันจะไม่ช่วยเพิ่มget|set
สำหรับthis.object
; ngOnChanges()
ตรวจพบการเปลี่ยนแปลง@Input
ของ sเท่านั้น มานาศักดิ์สิทธิ์! พวกเขาทำอะไรกับเรา ??? ให้เราดูลึก ๆ บางอย่าง!
หากคุณต้องการทำให้มีผลผูกพัน 2 ทางคุณสามารถใช้[(yourVar)]
แต่คุณต้องใช้yourVarChange
เหตุการณ์และเรียกมันว่าทุกครั้งที่มีการเปลี่ยนแปลงตัวแปร
บางอย่างเช่นนี้เพื่อติดตามการเปลี่ยนแปลงของฮีโร่
@Output() heroChange = new EventEmitter();
และเมื่อฮีโร่ของคุณได้รับการเปลี่ยนแปลงให้โทร this.heroChange.emit(this.hero);
[(hero)]
ผูกพันจะไม่เหลือสำหรับคุณ
ดูตัวอย่างที่นี่:
ลองนี้เมื่อใบสมัครของคุณยังคงเรียกร้อง$parse
, $eval
, $watch
เช่นพฤติกรรมในเชิงมุม
นี่ไม่ใช่คำตอบของคำถามโดยตรง แต่ฉันมีโอกาสต่าง ๆ กันในคำถาม Stack Overflow นี้เพื่อแก้ปัญหาบางอย่างที่ฉันจะใช้ $ watch สำหรับใน angularJs ฉันใช้วิธีอื่นมากกว่าที่อธิบายไว้ในคำตอบปัจจุบันและต้องการแบ่งปันในกรณีที่มีคนพบว่ามีประโยชน์
เทคนิคที่ฉันใช้เพื่อให้ได้สิ่งที่คล้ายกัน$watch
คือการใช้BehaviorSubject
( เพิ่มเติมในหัวข้อที่นี่ ) ในบริการเชิงมุมและให้ส่วนประกอบของฉันสมัครสมาชิกเพื่อรับการเปลี่ยนแปลง (ดู) สิ่งนี้คล้ายกับ$watch
angularJs แต่ต้องการการตั้งค่าและความเข้าใจเพิ่มเติม
ในองค์ประกอบของฉัน:
export class HelloComponent {
name: string;
// inject our service, which holds the object we want to watch.
constructor(private helloService: HelloService){
// Here I am "watching" for changes by subscribing
this.helloService.getGreeting().subscribe( greeting => {
this.name = greeting.value;
});
}
}
ในการบริการของฉัน
export class HelloService {
private helloSubject = new BehaviorSubject<{value: string}>({value: 'hello'});
constructor(){}
// similar to using $watch, in order to get updates of our object
getGreeting(): Observable<{value:string}> {
return this.helloSubject;
}
// Each time this method is called, each subscriber will receive the updated greeting.
setGreeting(greeting: string) {
this.helloSubject.next({value: greeting});
}
}
นี่คือตัวอย่างของStackblitz