什么是Angular2等同于AngularJS $手表?

在AngularJS中,您可以使用$watch scope的$watch函数指定观察者观察范围variables的变化。 在Angular2中观察variables变化(例如,组件variables)的等价物是什么?

在Angular 2中,更改检测是自动的… $scope.$watch()$scope.$digest() RIP

不幸的是,开发指南中的变化检测部分还没有写入(在“ 架构概述”页面的底部附近有一个占位符,在“其他的东西”部分)。

以下是我对变化检测如何工作的理解:

  • Zone.js“猴子修补世界” – 拦截浏览器中的所有asynchronousAPI(当Angular运行时)。 这就是为什么我们可以在组件内部使用setTimeout()而不是像$timeout这样的东西,因为setTimeout()是猴子修补的。
  • angular度build立和维护一个“变化探测器”的树。 每个组件/指令有一个这样的变化检测器(类)。 (您可以通过注入ChangeDetectorRef来访问此对象。)这些更改检测器是在Angular创build组件时创build的。 他们跟踪所有绑定的状态,用于脏检查。 这些在某种意义上类似于Angular 1为{{}}模板绑定设置​​的自动$watches()
    与Angular 1不同的是,变化检测图是一棵有向树,不能有循环(这使得Angular 2性能更高,我们将在下面看到)。
  • 当一个事件触发(在Angular区域内)时,我们写的代码(事件处理程序callback)运行。 它可以更新任何想要的数据 – 共享的应用程序模型/状态和/或组件的视图状态。
  • 之后,由于Zone.js添加了钩子,它运行Angular的变化检测algorithm。 默认情况下(即,如果您未在任何组件上使用onPush更改检测策略),树中的每个组件都会按深度优先顺序从顶部(TTL = 1)…检查一次。 (好吧,如果你处于开发模式,更改检测运行两次(TTL = 2 ) ,更多的信息请参阅ApplicationRef.tick() 。)使用这些更改检测器对象对所有绑定进行脏检查。
    • 生命周期钩子被称为变化检测的一部分。
      如果要观看的组件数据是原始input属性(string,布尔值,数字),则可以实现ngOnChanges()以通知更改。
      如果input属性是一个引用types(对象,数组等),但引用没有改变(例如,你添加一个项目到现有的数组),你需要实现ngDoCheck() (看到这个回答更多关于这个)。
      您应该只更改组件的属性和/或后代组件的属性(因为单树行走实现 – 即单向数据stream)。 这是一个违反这个规定的暴徒 。 有状态的pipe道也可以让你在这里。
  • 对于find的任何绑定更改,将更新组件,然后更新DOM。 更改检测现已完成。
  • 浏览器通知DOM更改并更新屏幕。

其他参考了解更多:

  • Angular的$摘要在Angular的新版本中重生 – 解释了如何将AngularJS的想法映射到Angular
  • 您需要了解有关Angular中变更检测的所有信息 – 详细解释变更检测是如何工作的
  • 更改检测说明 – 虽然tram博客2016年2月22日 – 可能是最好的参考
  • Savkin的变化检测重新发布的video – 绝对看这一个
  • angular度2变化检测如何真正的工作? – jhade的博客2016年2月24日
  • Brian的video和Miško关于Zone.js 的video Brian的是关于Zone.js的。 Miško的是关于Angular 2如何使用Zone.js来实现变化检测。 他还谈到了一般的变化检测,以及关于onPush
  • Victor Savkins博客文章: Angular 2中的变化检测 ,Angular 2应用程序的两个阶段 , Angular,Immutability和Encapsulation 。 他很快就覆盖了很多地面,但他有时可能会变得简单,而你却只是在挠挠头脑,想知道那些丢失的东西。
  • 超快速变化检测 (Google Doc) – 非常技术性,非常简洁,但它描述/绘制了作为树的一部分构build的ChangeDetection类

此行为现​​在是组件生命周期的一部分。

组件可以在OnChanges接口中实现ngOnChanges方法以访问input更改。

例:

 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 functionget accessor来充当angular2上的监视。

在这里看到演示。

 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; } } 

如果你想使它成为双向绑定,你可以使用[(yourVar)] ,但是你必须实现你的yourVarChange事件,并在每次variables变化时调用它。

像这样的东西来跟踪英雄的变化

 @Output() heroChange = new EventEmitter(); 

然后当你的英雄变了,调用this.heroChange.emit(this.hero);

[(hero)]绑定将为你做剩下的事情

看到这里的例子:

http://plnkr.co/edit/efOGIJ0POh1XQeRZctSx?p=preview