[英]What is the Angular equivalent to an AngularJS $watch?
In AngularJS you were able to specify watchers to observe changes in scope variables using the $watch
function of the $scope
.在 AngularJS 中,您可以使用 $ $scope
的$watch
函数指定观察者来观察作用域变量的变化。 What is the equivalent of watching for variable changes (in, for example, component variables) in Angular?在 Angular 中监视变量变化(例如,在组件变量中)有什么等价物?
In Angular 2, change detection is automatic... $scope.$watch()
and $scope.$digest()
RIP在 Angular 2 中,变化检测是自动的... $scope.$watch()
和$scope.$digest()
RIP
Unfortunately, the Change Detection section of the dev guide is not written yet (there is a placeholder near the bottom of the Architecture Overview page, in section "The Other Stuff").不幸的是,开发指南的变更检测部分尚未编写(在“架构概述”页面底部附近的“其他内容”部分中有一个占位符)。
Here's my understanding of how change detection works:这是我对变化检测如何工作的理解:
setTimeout()
inside our components rather than something like $timeout
... because setTimeout()
is monkey patched.这就是为什么我们可以在我们的组件中使用setTimeout()
而不是$timeout
之类的东西......因为setTimeout()
是猴子补丁。ChangeDetectorRef
.) These change detectors are created when Angular creates components. (你可以通过注入ChangeDetectorRef
来访问这个对象。)这些变化检测器是在 Angular 创建组件时创建的。 They keep track of the state of all of your bindings, for dirty checking.他们跟踪所有绑定的状态,以进行脏检查。 These are, in a sense, similar to the automatic $watches()
that Angular 1 would set up for {{}}
template bindings.从某种意义上说,这些类似于 Angular 1 为{{}}
模板绑定设置的自动$watches()
。onPush
change detection strategy on any of your components), every component in the tree is examined once (TTL=1)... from the top, in depth-first order.默认情况下(即,如果您没有在任何组件上使用onPush
更改检测策略),树中的每个组件都会被检查一次 (TTL=1)... 从顶部开始,按深度优先顺序。 (Well, if you're in dev mode, change detection runs twice (TTL=2). See ApplicationRef.tick() for more about this.) It performs dirty checking on all of your bindings, using those change detector objects. (好吧,如果您处于开发模式,更改检测会运行两次 (TTL=2)。请参阅ApplicationRef.tick()了解更多信息。)它使用这些更改检测器对象对您的所有绑定执行脏检查。
ngOnChanges()
to be notified of changes.如果您要查看的组件数据是原始输入属性(字符串、布尔值、数字),您可以实现ngOnChanges()
以收到更改通知。ngDoCheck()
(see this SO answer for more on this).如果输入属性是引用类型(对象、数组等),但引用没有改变(例如,您向现有数组添加了一个项目),则需要实现ngDoCheck()
(请参阅此 SO回答更多关于这个)。Other references to learn more:其他参考以了解更多信息:
onPush
.他还谈到了一般的变化检测,以及一些关于onPush
的话题。This behaviour is now part of the component lifecycle.此行为现在是组件生命周期的一部分。
A component can implement the ngOnChanges method in the OnChanges interface to get access to input changes.组件可以在OnChanges接口中实现 ngOnChanges 方法来访问输入更改。
Example:例子:
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);
}
}
If, in addition to automatic two-way binding, you want to call a function when a value changes, you can break the two-way binding shortcut syntax to the more verbose version.如果除了自动双向绑定之外,您还想在值更改时调用函数,则可以将双向绑定快捷语法改为更冗长的版本。
<input [(ngModel)]="yourVar"></input>
is shorthand for是简写
<input [ngModel]="yourVar" (ngModelChange)="yourVar=$event"></input>
(see eg http://victorsavkin.com/post/119943127151/angular-2-template-syntax ) (参见例如http://victorsavkin.com/post/119943127151/angular-2-template-syntax )
You could do something like this:你可以这样做:
<input [(ngModel)]="yourVar" (ngModelChange)="changedExtraHandler($event)"></input>
You can use getter function
or get accessor
to act as watch on angular 2.您可以使用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);
}
}
Here is another approach using getter and setter functions for the model.这是为模型使用 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;
}
}
If you want to make it 2 way binding, you can use [(yourVar)]
, but you have to implement yourVarChange
event and call it everytime your variable change.如果你想让它成为双向绑定,你可以使用[(yourVar)]
,但你必须实现yourVarChange
事件并在每次变量更改时调用它。
Something like this to track the hero change像这样跟踪英雄变化
@Output() heroChange = new EventEmitter();
and then when your hero get changed, call this.heroChange.emit(this.hero);
然后当你的英雄改变时,调用this.heroChange.emit(this.hero);
the [(hero)]
binding will do the rest for you [(hero)]
绑定将为您完成剩下的工作
see example here:看这里的例子:
http://plnkr.co/edit/efOGIJ0POh1XQeRZctSx?p=preview http://plnkr.co/edit/efOGIJ0POh1XQeRZctSx?p=preview
This does not answer the question directly, but I have on different occasions landed on this Stack Overflow question in order to solve something I would use $watch for in angularJs.这并没有直接回答这个问题,但是我在不同的场合遇到了这个 Stack Overflow 问题,以解决我会在 angularJs 中使用 $watch 的问题。 I ended up using another approach than described in the current answers, and want to share it in case someone finds it useful.我最终使用了当前答案中描述的另一种方法,并希望分享它以防有人发现它有用。
The technique I use to achieve something similar $watch
is to use a BehaviorSubject
( more on the topic here ) in an Angular service, and let my components subscribe to it in order to get (watch) the changes.我用来实现类似$watch
的技术是在 Angular 服务中使用BehaviorSubject
( 更多关于主题),并让我的组件订阅它以获取(观察)更改。 This is similar to a $watch
in angularJs, but require some more setup and understanding.这类似于 angularJs 中的$watch
,但需要更多设置和理解。
In my component:在我的组件中:
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;
});
}
}
In my service在我的服务中
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});
}
}
Here is a demo on Stackblitz这是Stackblitz上的演示
In AngularJS you were able to specify watchers to observe changes in scope variables using the $watch
function of the $scope
.在AngularJS你能够指定观察者,观察使用范围变量的变化$watch
的功能$scope
。 What is the equivalent of watching for variable changes (in, for example, component variables) in Angular?在 Angular 中观察变量变化(例如,组件变量)的等价物是什么?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.