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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46330070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:24:06  来源:igfitidea点击:

Angular 4: How to watch an object for changes?

javascriptangulartypescript

提问by greenie2600

ETA: I know that there are various ways to watch my formfor changes. That is not what I am trying to do. As the title says, I am asking how to watch for changes to an object. The app shown below is for illustration purposes only. Please answer the question that I have asked. Thanks!

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

I have this simple app:

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

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?

    }

}

Note the TODO. I need to register a callback that will run whenever any property of this.customerhas been changed.

注意 TODO。我需要注册一个回调,该回调将在 的任何属性 this.customer发生更改时运行。

I cannot use ngChange on the inputs. I need to subscribe directly to changes on the model.The reasons pertain to my use case, and aren't worth going into here. Just trust me that this isn't an option.

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

Is this possible? I've done a lot of Googling, but I've come up dry.

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

回答by yurzui

Angular usually uses injected into constructor KeyValueDiffersclass.

Angular 通常使用注入到构造函数中的KeyValueDiffers类。

For your case it could look like:

对于您的情况,它可能如下所示:

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

Stackblitz 示例

One more option is using setter on properties that you want to check.

另一种选择是在要检查的属性上使用 setter。

See also

也可以看看

回答by Vega

I need to subscribe directly to changes on the model.

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

Then you need to listen to model changes with ngModelChange

然后你需要听模型变化 ngModelChange

Template:

模板:

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

Class:

班级

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

DEMO

演示

回答by alexKhymenko

You can't watch changes in an object. Its not angular 1there are no watchers here. Another solution will be via observables.

您无法观察对象的变化。它不是 angular 1,这里没有观察者。另一种解决方案是通过 observables。

use form

使用表格

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

in code

在代码中

@ViewChild('f') f;

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

回答by John Montgomery

You could use custom setters to trigger your callback:

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

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

Then just assign the callback when you create the object:

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

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

// or

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

回答by u8354979

visit https://github.com/cartant/rxjs-observe. it bases on rxjs and proxy.

访问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";

回答by madjardi

You can see this articlemaybe it help.

你可以看看这篇文章也许有帮助。

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