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