首页 文章

什么是Angular相当于AngularJS $ Watch ?

提问于
浏览
191

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

7 回答

  • 11

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

    遗憾的是,开发指南的“更改检测”部分尚未编写(Architecture Overview页面底部附近有一个占位符,位于"The Other Stuff"部分) .

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

    • Zone.js "monkey patches the world" - 它拦截浏览器中的所有异步API(当Angular运行时) . 这就是为什么我们可以在我们的组件中使用 setTimeout() 而不是 $timeout ...因为 setTimeout() 是猴子修补的 .

    • Angular构建并维护"change detectors"的树 . 每个组件/指令有一个这样的变化检测器(类) . (您可以通过注入ChangeDetectorRef来访问此对象 . )当Angular创建组件时,会创建这些更改检测器 . 它们会跟踪所有绑定的状态,以便进行脏检查 . 从某种意义上说,这些类似于Angular 1为 {{}} 模板绑定设置的自动 $watches() .
      与Angular 1不同,变化检测图是一个有向树,不能有循环(这使得Angular 2的性能更高,我们将在下面看到) .

    • 当事件触发时(在Angular区域内),我们编写的代码(事件处理程序回调)运行 . 它可以更新它想要的任何数据 - 共享应用程序模型/状态和/或组件的视图状态 .

    • 之后,由于添加了挂钩Zone.js,它会运行Angular的变化检测算法 . 默认情况下(即,如果您未在任何组件上使用 onPush 更改检测策略),树中的每个组件都将从顶部按深度优先顺序检查一次(TTL = 1).... (好吧,如果您处于开发模式,更改检测会运行两次(TTL = 2) . 有关详细信息,请参阅ApplicationRef.tick() . )它使用这些更改检测器对象对所有绑定执行脏检查 .

    • 生命周期钩子被称为变化检测的一部分 .
      如果要监视的组件数据是原始输入属性(String,boolean,number),则可以实现 ngOnChanges() 以通知更改 .
      如果input属性是引用类型(对象,数组等),但引用并不需要实现 ngDoCheck() (有关详细信息,请参阅this SO answer) .
      您应该只更改违反该组件的组件's properties and/or properties of descendant components (because of the single tree walk implementation -- i.e., unidirectional data flow). Here' s a plunker . 有状态的管道也可以在这里trip you up .

    • 对于找到的任何绑定更改,将更新组件,然后更新DOM . 变更检测现已完成 .

    • 浏览器通知DOM更改并更新屏幕 .

    其他参考资料了解更多:

  • 253

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

    组件可以在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);
      }
    }
    
  • 3

    如果除了自动双向绑定之外,您希望在值更改时调用函数,则可以将双向绑定快捷方式语法分解为更详细的版本 .

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

  • 84

    您可以使用 getter functionget accessor 作为角度2的监视 .

    见演示here .

    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);
        }
    }
    
  • 62

    这是另一种使用模型的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;
      }
    }
    
  • 5

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

    像这样追踪英雄变化的东西

    @Output() heroChange = new EventEmitter();
    

    然后当你的英雄变了,请拨打 this.heroChange.emit(this.hero);

    [(hero)] 绑定将为您完成剩下的工作

    看这里的例子:

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

  • 14

    当您的应用程序 still 在Angular中要求 $parse$eval$watch 之类的行为时请尝试此操作

    https://github.com/vinayk406/angular-expression-parser

相关问题