Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 角度4:如何观察对象的变化?_Javascript_Angular_Typescript - Fatal编程技术网

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

Javascript 角度4:如何观察对象的变化?,javascript,angular,typescript,Javascript,Angular,Typescript,ETA:我知道有多种方法可以观察我的状态变化。这不是我想要做的。正如标题所说,我在问如何监视对象的更改。下面显示的应用程序仅用于说明目的。请回答我提出的问题。谢谢 我有一个简单的应用程序: import { Component, OnInit } from '@angular/core'; export class Customer { firstName: string; favoriteColor: string; } @Component({ selector:

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?

    }

}
从'@angular/core'导入{Component,OnInit};
出口类客户{
名字:字符串;
收藏夹颜色:字符串;
}
@组成部分({
选择器:“我的应用程序”,
模板:`
`
})
导出类AppComponent实现OnInit{
私人客户:客户;
ngOnInit():void{
this.customer=新客户();
//TODO:如何注册随时运行的回调
//此客户的任何属性已更改?
}
}
注意待办事项。我需要注册一个回调,该回调将在
this.customer
的任何属性发生更改时运行

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


这可能吗?我在谷歌上搜索了很多次,但都没有搜索结果。

你无法观察对象的变化不是棱角分明的1这里没有观察者。另一个解决方案是通过观察

使用形式

<form #f="ngForm">
  <input type="text" name="firstName" [(ngModel)]="customer.firstName">
  <input type="text" name="favoriteColor" [(ngModel)]="customer.favoriteColor">
</form>
我需要直接订阅模型上的更改

然后,您需要使用
ngModelChange

模板:

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

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

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

import{KeyValueChanges,keyValueDifference,keyValueDifferences}来自“@angular/core”;
出口类客户{
名字:字符串;
收藏夹颜色:字符串;
}
@组成部分({
选择器:“我的应用程序”,
templateUrl:`./app.component.html`
})
导出类AppComponent{
私人客户定义:keyValueDifferent;
私人客户:客户;
构造函数(private-differences:keyValueDifferences){}
ngOnInit():void{
this.customer=新客户();
this.customerDiffer=this.differences.find(this.customer.create();
}
customerChanged(更改:KeyValueChanges){
console.log('changes');
/*如果您想查看详细信息,请使用
更改。forEachRemovedItem((记录)=>…);
更改。ForEachAddItem((记录)=>…);
forEachChangedItem((记录)=>…);
*/
}
ngDoCheck():void{
const changes=this.customerDiffer.diff(this.customer);
如果(更改){
本.客户变更(变更);
}
}
}

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

另见


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

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)
访问。它基于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";

我们的任务是将Angular 1.x应用程序转换为Angular 9。它是一个带有ESRI映射的应用程序,因此我们有一些ESRI框架带来的简洁工具。ESRI的watchUtils所做的远远不止是观察变化

但我错过了Angular 1的简单美元手表。此外,我们在应用程序中创建实体和模型,我们可能需要不时观察这些实体和模型

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


这个类的另一个映射是_propertyChangeMap:Map使用反应式表单,并使用FormGroup公开的valueChanges。这些输入是任何形式的吗?如果他们不是,他们应该是。如果他们订阅了表单的更改,那么表单的状态和对象的状态是相同的。您无法侦听对象上的更改。但是,由于每次表单更改时,模型也会更改,因此监听表单上的更改基本上等同于监听对象上的更改。您是否尝试过在每个客户对象上附加一个简单的getter/setter?老实说,我甚至不确定这是否可能,但我想我会把它扔出去。你可能已经弄明白了吗?令人惊讶的是,没有简单的方法可以做到这一点。。在我看来,这是一种常见的构造块。Angular4自动将novalidate设置为ngForms:-)直接从他们的文档@Mihailo中获取,但已删除:-)应在文档上打开pull请求我必须使用
setTimeout()
以确保使用新值更新模型在我对变更采取行动之前……这是我发现唯一有效的方法,但无论如何,这都不是干净或简单的方法,我们没有更好的方法来处理“对象属性已更改,请告诉我”我必须使用这个答案和下面@alexKhymenko的答案相结合,以确保我的代码注意到所有的更改。
this.customer = new Customer((oldVal, newVal) => console.log(oldVal, newVal))

// or

this.customer = new Customer()
this.customer.valueChanged = (oldVal, newVal) => console.log(oldVal, newVal)
import { observe } from "rxjs-observe";

const instance = { name: "Alice" };
const { observables, proxy } = observe(instance);
observables.name.subscribe(value => console.log(name));
proxy.name = "Bob";
public get foo(): string {
    return this._get("foo");
}  
public set foo(value:string) {
    this._set("foo", value);
}


--------------------------------------------------------------------
import { EventEmitter } from '@angular/core';

export abstract class MappedPropertyClass {
    private _properties: Map<string, any>;
    private _propertyChangeMap: Map<string, EventEmitter<{ newvalue, oldvalue }>>;

    protected _set(propertyName: string, propertyValue: any) {
        let oldValue = this._get(propertyName);
        this._properties.set(propertyName, propertyValue);
        this.getPropertyChangeEmitter(propertyName).emit({ newvalue: 
    propertyValue, oldvalue: oldValue });
    }

    protected _get(propertyName: string): any {
        if (!this._properties.has(propertyName)) {
            this._properties.set(propertyName, undefined);
        } 
        return this._properties.get(propertyName);
    }

    protected get properties(): Map<string, any> {
        var props = new Map<string, any>();
        for (let key of this._properties.keys()) {
            props.set(key, this._properties.get(key));
        }

        return props;
    }

    protected constructor() {
        this._properties = new Map<string, any>();
        this._propertyChangeMap = new Map<string, EventEmitter<{ newvalue: any, 
        oldvalue: any }>>();
    }

    private getPropertyChangeEmitter(propertyName: string): EventEmitter<{ 
                         newvalue, oldvalue }> {
        if (!this._propertyChangeMap.has(propertyName)) {
            this._propertyChangeMap.set(propertyName, new EventEmitter<{ newvalue, 
            oldvalue }>());
        }
        return this._propertyChangeMap.get(propertyName);
    }

    public $watch(propertyName: string, callback: (newvalue, oldvalue) => void): 
    any {
        return this.getPropertyChangeEmitter(propertyName).subscribe((results) => 
        {
            callback(results.newvalue, results.oldvalue);
        });
    }
}