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

时间:2017-09-20 19:13:22

标签: angular

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

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

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "ConferenceUserCell", for: indexPath) as! ConferenceDetail_TVCell

        // Configure the cell...

        return cell
    }

请注意TODO。我需要注册一个回调,只要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? } } 的任何属性发生变化,它就会运行。

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

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

7 个答案:

答案 0 :(得分:22)

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

<强> Stackblitz Example

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

另见

答案 1 :(得分:19)

  

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

然后,您需要使用ngModelChange

收听模型更改

模板:

<input type="text" (ngModelChange)="doSomething($event)" [ngModel]="customer.firstName">

<强>类

doSomething(event) {
  console.log(event); // logs model value
}

DEMO

答案 2 :(得分:7)

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

使用表格

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

代码

@ViewChild('f') f;

ngAfterViewInit() {
  this.f.form.valueChanges.subscribe((change) => {
   console.log(change)
  })
}

答案 3 :(得分:2)

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

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 || (() => {})
  }
}

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

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

// or

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

答案 4 :(得分:1)

访问https://github.com/cartant/rxjs-observe。它基于rxjs和代理。

import { observe } from "rxjs-observe";

const instance = { name: "Alice" };
const { observables, proxy } = observe(instance);
observables.name.subscribe(value => console.log(name));
proxy.name = "Bob";

答案 5 :(得分:1)

我们的任务是将Angular 1.x应用程序转换为Angular9。这是一个具有ESRI映射的应用程序,因此我们将ESRI框架带到表格中使用了一些简洁的工具。 ESRI的watchUtils不仅可以监视更改,还可以做很多事情。

但是我错过了Angular 1的简单$ watch。此外,我们在应用程序中创建实体和模型,我们可能需要不时观察它们。

我创建了一个名为MappedPropertyClass的抽象类。它使用Map 映射类属性,这使我可以轻松实现toJSON和其他实用程序功能。

该类具有的另一个Map是_propertyChangeMap:Map ;

我们还有一个名为$ watch的函数,它带有一个字符串和一个回调函数。

此类可以由Entities以及组件或服务扩展

我很高兴与您分享,请注意,您的财产必须如下所示:

# `myfunc` implements the matrix-vector product for your linear operator
def myfunc(x, y=0):
    '''Implments the matrix-vector product for vector `x` and additional parameter `y`'''
    pass

shape =  # <the shape of your linear operator>
y =  # <the value of the parameter you want to use>
L = LinearOperator(shape, matvec=lambda x: myfunc(x, y))

# Then you can do:
x =  # <some vector>
b = L @ x  # note: `@` is the matrix multiply operation
# Now `b` will contain the result of `myfunc(x, y)

答案 6 :(得分:0)

您会看到this article可能有帮助。

constructor(private ref: ChangeDetectorRef) {}
removeSomthing(){
    this.items.split(idx, 1);
    // run manually watcher
    this.ref.detectChanges();
}