Angular 4:如何观察对象的变化?

gre*_*600 20 javascript typescript angular

ETA:我知道有多种方法可以观察我的表单以进行更改.这不是我想要做的.正如标题所说,我在问如何观察对象的变化.下面显示的应用程序仅用于说明目的.请回答我提出的问题.谢谢!

我有这个简单的应用程序:

import { Component, OnInit } from '@angular/core';

export class Customer {
    firstName: string;
    favoriteColor: string;
}

@Component({
    selector: 'my-app',
    template: `
        <div *ngIf="customer">
            <input type="text" [(ngModel)]="customer.firstName">
            <input type="text" [(ngModel)]="customer.favoriteColor">
        </div>
        `
})
export class AppComponent implements OnInit {

    private customer: Customer;

    ngOnInit(): void {

        this.customer = new Customer();

        // TODO: how can I register a callback that will run whenever
        // any property of this.customer has been changed?

    }

}
Run Code Online (Sandbox Code Playgroud)

注意TODO.我需要注册一个回调,它将在任何属性 this.customer发生变化时运行.

我不能在输入上使用ngChange.我需要直接订阅模型的更改.原因与我的用例有关,不值得进入这里.请相信我,这不是一个选择.

这可能吗?我做了很多谷歌搜索,但我已经干了.

yur*_*zui 26

Angular通常使用注入构造函数KeyValueDiffers类.

对于您的情况,它可能看起来像:

import { KeyValueChanges, KeyValueDiffer, KeyValueDiffers } from '@angular/core';

export class Customer {
  firstName: string;
  favoriteColor: string;
}

@Component({
  selector: 'my-app',
  templateUrl: `./app.component.html`
})
export class AppComponent {
  private customerDiffer: KeyValueDiffer<string, any>;
  private customer: Customer;

  constructor(private differs: KeyValueDiffers) {}

  ngOnInit(): void {
    this.customer = new Customer();
    this.customerDiffer = this.differs.find(this.customer).create();
  }

  customerChanged(changes: KeyValueChanges<string, any>) {
    console.log('changes');
    /* If you want to see details then use
      changes.forEachRemovedItem((record) => ...);
      changes.forEachAddedItem((record) => ...);
      changes.forEachChangedItem((record) => ...);
    */
  }

  ngDoCheck(): void {
      const changes = this.customerDiffer.diff(this.customer);
      if (changes) {
        this.customerChanged(changes);
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

Stackblitz示例

还有一个选项是在要检查的属性上使用setter.

也可以看看

  • 这是我发现有效的唯一方法,但恕我直言,这不是*干净*或*简单*任何方式,它很糟糕,我们没有提供更好的方法来处理"对象属性已更改,让我知道"情况比必须使用10行模式来完成它. (10认同)
  • 我同意@pootzko (2认同)

Veg*_*ega 21

我需要直接订阅模型的更改.

然后你需要听取模型的变化 ngModelChange

模板:

<input type="text" (ngModelChange)="doSomething($event)" [ngModel]="customer.firstName">
Run Code Online (Sandbox Code Playgroud)

课程:

doSomething(event) {
  console.log(event); // logs model value
}
Run Code Online (Sandbox Code Playgroud)

DEMO


ale*_*nko 8

您无法观察对象中的更改.它没有角度1,这里没有观察者.另一种解决方案是通过观察.

使用表格

<form #f="ngForm">
  <input type="text" name="firstName" [(ngModel)]="customer.firstName">
  <input type="text" name="favoriteColor" [(ngModel)]="customer.favoriteColor">
</form>
Run Code Online (Sandbox Code Playgroud)

在代码中

@ViewChild('f') f;

ngAfterViewInit() {
  this.f.form.valueChanges.subscribe((change) => {
   console.log(change)
  })
}
Run Code Online (Sandbox Code Playgroud)

  • Angular4自动将**无效**设置为ngForms. (3认同)

Joh*_*ery 6

您可以使用自定义设置器来触发您的回调:

class Customer {
  private _firstName: string
  get firstName(): string {
    return this._firstName
  }
  set firstName(firstName: string) {
    this.valueChanged(this._firstName, firstName)
    this._firstName = firstName
  }

  private _lastName: string
  get lastName(): string {
    return this._lastName
  }
  set lastName(lastName: string) {
    this.valueChanged(this._lastName, lastName)
    this._lastName = lastName
  }

  valueChanged: (oldVal, newVal) => void

  constructor (valueChanged?: (oldVal, newVal) => void) {
    // return an empty function if no callback was provided in case you don't need
    // one or want to assign it later
    this.valueChanged = valueChanged || (() => {})
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在创建对象时分配回调:

this.customer = new Customer((oldVal, newVal) => console.log(oldVal, newVal))

// or

this.customer = new Customer()
this.customer.valueChanged = (oldVal, newVal) => console.log(oldVal, newVal)
Run Code Online (Sandbox Code Playgroud)