У AngularJS ви змогли вказати спостерігачам спостерігати за змінами змінних областей за допомогою $watch
функції $scope
. Який еквівалент перегляду змін змінних (наприклад, змінних компонентів) у Angular?
У AngularJS ви змогли вказати спостерігачам спостерігати за змінами змінних областей за допомогою $watch
функції $scope
. Який еквівалент перегляду змін змінних (наприклад, змінних компонентів) у Angular?
Відповіді:
У куті 2 виявлення змін є автоматичним ... $scope.$watch()
та $scope.$digest()
RIP
На жаль, розділ Виявлення змін у посібнику розробників ще не написаний (у нижній частині сторінки " Огляд архітектури " в розділі "Інші речі" є заповнювач .
Ось моє розуміння того, як працює виявлення змін:
setTimeout()
всередині наших компонентів, а не щось на зразок $timeout
... тому що setTimeout()
це мавпа.ChangeDetectorRef
.) Ці детектори змін створюються, коли Angular створює компоненти. Вони відслідковують стан усіх ваших прив’язок, для брудної перевірки. Вони в певному сенсі схожі на автомати, $watches()
які Angular 1 встановив би для {{}}
прив'язки шаблонів. onPush
стратегію виявлення змін на жодному зі своїх компонентів), кожен компонент у дереві перевіряється один раз (TTL = 1) ... зверху, в глибині першого порядку. (Добре, якщо ви перебуваєте в режимі розробки, виявлення змін запускається двічі (TTL = 2). Докладніше про це див. У ApplicationRef.tick () .) Він здійснює брудну перевірку всіх ваших прив'язок, використовуючи ці об'єкти детектора змін.
ngOnChanges()
щоб отримувати повідомлення про зміни. ngDoCheck()
(див. Цю відповідь ТА для отримання додаткової інформації на цьому). Інші посилання, щоб дізнатися більше:
onPush
.host
Документацію "Слухачі хостів" в API DocumMetadata API, док . Він пояснює, як слухати глобальні події зсередини кутової зони (тому виявлення змін буде запускатися за бажанням). У цій відповіді працює планкер.
Така поведінка зараз є частиною життєвого циклу компонентів.
Компонент може реалізувати метод 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);
}
}
Якщо, крім автоматичного двостороннього прив'язки, ви хочете викликати функцію, коли значення змінюється, ви можете розбити синтаксис ярлика двостороннього зв’язування на більш багатослівну версію.
<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)
обробники на кожну з них; Я не хочу додавати get|sets
s до кожної властивості моєї моделі; це не допоможе додати get|set
для this.object
; ngOnChanges()
виявляє зміни лише до @Input
s . Свята манна! Що вони з нами зробили ??? Поверніть нам якийсь глибокий годинник!
Якщо ви хочете зробити це двостороннім обов'язковим, ви можете використовувати [(yourVar)]
, але ви повинні реалізувати yourVarChange
подію та викликати її щоразу, коли зміна вашої змінної.
Щось подібне для відстеження змін героя
@Output() heroChange = new EventEmitter();
а потім, коли ваш герой зміниться, дзвоніть this.heroChange.emit(this.hero);
[(hero)]
зв'язуванні інше зробить за вас
див. приклад тут:
Спробуйте це , коли ваш додаток все ще вимагає $parse
, $eval
, $watch
як поведінка в кутових
Це не відповідає на питання безпосередньо, але я неодноразово опинявся на цьому запитанні переповнення стека, щоб вирішити щось, для чого я би використовував $ watch у angularJs. Я в кінцевому підсумку використовував інший підхід, ніж описано в поточних відповідях, і хочу поділитися ним у випадку, якщо хтось вважає це корисним.
Метод, який я використовую для досягнення чогось подібного, $watch
полягає у використанні BehaviorSubject
( докладніше про тему тут ) у службі Angular, і дозволити моїм компонентам підписатися на нього, щоб отримати (переглянути) зміни. Це схоже на $watch
кутовий J, але вимагає додаткової настройки та розуміння.
У моєму компоненті:
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