簡體   English   中英

AngularJS $watch 的 Angular 等價物是什么?

[英]What is the Angular equivalent to an AngularJS $watch?

在 AngularJS 中,您可以使用 $ $scope$watch函數指定觀察者來觀察作用域變量的變化。 在 Angular 中監視變量變化(例如,在組件變量中)有什么等價物?

在 Angular 2 中,變化檢測是自動的... $scope.$watch()$scope.$digest() RIP

不幸的是,開發指南的變更檢測部分尚未編寫(在“架構概述”頁面底部附近的“其他內容”部分中有一個占位符)。

這是我對變化檢測如何工作的理解:

  • Zone.js “monkey patches the world”——它攔截瀏覽器中的所有異步 API(當 Angular 運行時)。 這就是為什么我們可以在我們的組件中使用setTimeout()而不是$timeout之類的東西......因為setTimeout()是猴子補丁。
  • Angular 構建並維護一個“變化檢測器”樹。 每個組件/指令都有一個這樣的變化檢測器(類)。 (你可以通過注入ChangeDetectorRef來訪問這個對象。)這些變化檢測器是在 Angular 創建組件時創建的。 他們跟蹤所有綁定的狀態,以進行臟檢查。 從某種意義上說,這些類似於 Angular 1 為{{}}模板綁定設置的自動$watches()
    與 Angular 1 不同,變化檢測圖是一棵有向樹並且不能有循環(這使得 Angular 2 的性能更高,我們將在下面看到)。
  • 當事件觸發時(在 Angular 區域內),我們編寫的代碼(事件處理程序回調)運行。 它可以更新它想要的任何數據——共享應用程序模型/狀態和/或組件的視圖狀態。
  • 之后,由於添加了掛鈎 Zone.js,它會運行 Angular 的變更檢測算法。 默認情況下(即,如果您沒有在任何組件上使用onPush更改檢測策略),樹中的每個組件都會被檢查一次 (TTL=1)... 從頂部開始,按深度優先順序。 (好吧,如果您處於開發模式,更改檢測會運行兩次 (TTL=2)。請參閱ApplicationRef.tick()了解更多信息。)它使用這些更改檢測器對象對您的所有綁定執行臟檢查。
    • 生命周期掛鈎被稱為變更檢測的一部分。
      如果您要查看的組件數據是原始輸入屬性(字符串、布爾值、數字),您可以實現ngOnChanges()以收到更改通知。
      如果輸入屬性是引用類型(對象、數組等),但引用沒有改變(例如,您向現有數組添加了一個項目),則需要實現ngDoCheck() (請參閱此 SO回答更多關於這個)。
      您應該只更改組件的屬性和/或后代組件的屬性(因為單樹遍歷實現——即單向數據流)。 這里有一個 plunker違反了這一點。 有狀態的管道也可以讓你在這里絆倒
  • 對於找到的任何綁定更改,將更新組件,然后更新 DOM。 更改檢測現已完成。
  • 瀏覽器注意到 DOM 更改並更新屏幕。

其他參考以了解更多信息:

此行為現在是組件生命周期的一部分。

組件可以在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);
  }
}

如果除了自動雙向綁定之外,您還想在值更改時調用函數,則可以將雙向綁定快捷語法改為更冗長的版本。

<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充當角度 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;
  }
}

如果你想讓它成為雙向綁定,你可以使用[(yourVar)] ,但你必須實現yourVarChange事件並在每次變量更改時調用它。

像這樣跟蹤英雄變化

@Output() heroChange = new EventEmitter();

然后當你的英雄改變時,調用this.heroChange.emit(this.hero);

[(hero)]綁定將為您完成剩下的工作

看這里的例子:

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

這並沒有直接回答這個問題,但是我在不同的場合遇到了這個 Stack Overflow 問題,以解決我會在 angularJs 中使用 $watch 的問題。 我最終使用了當前答案中描述的另一種方法,並希望分享它以防有人發現它有用。

我用來實現類似$watch的技術是在 Angular 服務中使用BehaviorSubject更多關於主題),並讓我的組件訂閱它以獲取(觀察)更改。 這類似於 angularJs 中的$watch ,但需要更多設置和理解。

在我的組件中:

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上的演示

在AngularJS你能夠指定觀察者,觀察使用范圍變量的變化$watch的功能$scope 在 Angular 中觀察變量變化(例如,組件變量)的等價物是什么?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM