在AngularJS中,您可以使用$watch
函数来指定观察者观察范围变量的变化$scope
.在Angular中观察变量(例如,组件变量)的等价物是什么?
在Angular 2中,更改检测是自动的...... $scope.$watch()
和$scope.$digest()
RIP
遗憾的是,开发指南的"更改检测"部分尚未编写(" 架构概述"页面底部附近有一个占位符,位于"其他内容"部分).
以下是我对变更检测如何工作的理解:
Zone.js"猴子修补世界" - 它拦截浏览器中的所有异步API(当Angular运行时).这就是为什么我们可以setTimeout()
在我们的组件内使用而不是像$timeout
...因为setTimeout()
猴子修补.
Angular构建并维护一个"变化探测器"树.每个组件/指令有一个这样的变化检测器(类).(您可以通过注入来访问此对象ChangeDetectorRef
.)当Angular创建组件时,会创建这些更改检测器.它们会跟踪所有绑定的状态,以便进行脏检查.从某种意义上说,这些类似于$watches()
Angular 1为{{}}
模板绑定设置的自动化.
与Angular 1不同,变化检测图是一个有向树,不能有循环(这使得Angular 2的性能更高,我们将在下面看到).
当事件触发时(在Angular区域内),我们编写的代码(事件处理程序回调)运行.它可以更新它想要的任何数据 - 共享应用程序模型/状态和/或组件的视图状态.
之后,由于添加了钩子Zone.js,它然后运行Angular的变化检测算法.默认情况下(即,如果您未onPush
在任何组件上使用更改检测策略),树中的每个组件都会从顶部按深度优先顺序检查一次(TTL = 1).(好吧,如果您处于开发模式,更改检测会运行两次(TTL = 2).有关此内容,请参阅ApplicationRef.tick().)它使用这些更改检测器对象对所有绑定执行脏检查.
生命周期钩子被称为变化检测的一部分.
如果要监视的组件数据是原始输入属性(String,boolean,number),则可以实现ngOnChanges()
更改通知.
如果输入属性是引用类型(对象,数组等),但引用没有改变(例如,您将项添加到现有数组),则需要实现ngDoCheck()
(请参阅此SO答案以获取更多信息)在此).
您应该只更改组件的后代组件的属性和/或属性(因为单个树步行实现 - 即单向数据流).这是一个违反这一点的掠夺者.有状态的管道也可以在这里绊倒你.
对于找到的任何绑定更改,将更新组件,然后更新DOM.变更检测现已完成.
浏览器会注意到DOM更改并更新屏幕.
其他参考资料了解更多:
Angular的$ digest在较新版本的Angular中重生 - 解释了AngularJS的想法是如何映射到Angular的
您需要了解的有关Angular中变更检测的所有信息 - 详细解释了变更检测在引擎盖下的工作原理
变化检测解释 - 虽然tram博客2016年2月22日 - 可能是最好的参考
Savkin的变化检测重新发明的视频 - 绝对要看这个
Angular 2变化检测如何真正起作用? - jhade的博客2016年2月24日
Brian的视频和Miško关于Zone.js 的视频.Brian的是关于Zone.js. Miško是关于Angular 2如何使用Zone.js来实现变化检测.他还谈到了一般的变化检测,以及一点点onPush
.
维克多Savkins博客文章:变化检测在角2,折角2个应用两个阶段,棱角分明,不变性和封装.他很快就覆盖了很多地方,但有时他可能会很简洁,而你却一直在挠头,想知道丢失的碎片.
超快速变化检测(Google doc) - 非常技术性,非常简洁,但它描述/草绘了作为树的一部分构建的ChangeDetection类
此行为现在是组件生命周期的一部分.
组件可以在OnChanges接口中实现ngOnChanges方法以访问输入更改.
例:
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);
}
}
如果除了自动双向绑定之外,您希望在值更改时调用函数,则可以将双向绑定快捷方式语法分解为更详细的版本.
是简写
(参见http://victorsavkin.com/post/119943127151/angular-2-template-syntax)
你可以这样做:
您可以使用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: `
I'm array 1 {{ array1 | json }}
I'm array 2 {{ array2 | json }}
I'm concatenated {{ concatenatedArray | json }}
I'm length of two arrays {{ arrayLength | json }}
`
})
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: ` … `, }) export class InputLanguageComponent { set query(value) { this._query = value; console.log('query set to :', value) } get query() { return this._query; } }
如果你想使它成双向绑定,你可以使用[(yourVar)]
,但你必须实现yourVarChange
事件并在每次变量变化时调用它.
像这样追踪英雄变化的东西
@Output() heroChange = new EventEmitter();
然后当你的英雄变了,打电话 this.heroChange.emit(this.hero);
在[(hero)]
结合将完成剩下的你
看这里的例子:
http://plnkr.co/edit/efOGIJ0POh1XQeRZctSx?p=preview