如何从类属性 TypeScript - Angular 中监听值的变化

新手上路,请多包涵

在 AngularJS 中,我们可以使用 $watch , $digest 来监听变量的变化……新版本的 Angular (5, 6) 不再可能。

在 Angular 中,这种行为现在是组件生命周期的一部分。

我查看了官方文档、文章,尤其是 关于可变对象的 Angular 5 变化检测,以了解如何监听 TypeScript 类/ Angular 中的变量(类属性)变化

今天提出的是:

 import { OnChanges, SimpleChanges, DoCheck } from '@angular/core';

@Component({
  selector: 'my-comp',
  templateUrl: 'my-comp.html',
  styleUrls: ['my-comp.css'],
  inputs:['input1', 'input2']
})
export class MyClass implements OnChanges, DoCheck, OnInit{

  //I can track changes for this properties
  @Input() input1:string;
  @Input() input2:string;

  //Properties what I want to track !
  myProperty_1: boolean
  myProperty_2: ['A', 'B', 'C'];
  myProperty_3: MysObject;

  constructor() { }

  ngOnInit() { }

  //Solution 1 - fired when Angular detects changes to the @Input properties
  ngOnChanges(changes: SimpleChanges) {
    //Action for change
  }

  //Solution 2 - Where Angular fails to detect the changes to the input property
  //the DoCheck allows us to implement our custom change detection
  ngDoCheck() {
    //Action for change
  }
}

这仅适用于 @Input() 属性!

如果我想跟踪组件自身属性的变化( myProperty_1myProperty_2myProperty_3 ),这将不起作用。

有人可以帮我解决这个问题吗?最好是与 Angular 5 兼容的解决方案

原文由 L Y E S - C H I O U K H 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

您仍然可以通过 KeyValueDiffers 通过 DoCheck lifehook 检查组件的字段成员值更改。

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

differ: KeyValueDiffer<string, any>;
constructor(private differs: KeyValueDiffers) {
  this.differ = this.differs.find({}).create();
}

ngDoCheck() {
  const change = this.differ.diff(this);
  if (change) {
    change.forEachChangedItem(item => {
      console.log('item changed', item);
    });
  }
}

演示

原文由 Pengyy 发布,翻译遵循 CC BY-SA 4.0 许可协议

我认为解决你的问题最好的方法是使用一个装饰器自动用一个属性替换原始字段,然后在设置器上你可以创建一个 SimpleChanges 对象类似于由角度创建的对象以便使用与角度相同的通知回调(或者您可以为这些通知创建不同的接口,但适用相同的原则)

 import { OnChanges, SimpleChanges, DoCheck, SimpleChange } from '@angular/core';

function Watch() : PropertyDecorator & MethodDecorator{
    function isOnChanges(val: OnChanges): val is OnChanges{
        return !!(val as OnChanges).ngOnChanges
    }
    return (target : any, key: string | symbol, propDesc?: PropertyDescriptor) => {
        let privateKey = "_" + key.toString();
        let isNotFirstChangePrivateKey = "_" + key.toString() + 'IsNotFirstChange';
        propDesc = propDesc || {
            configurable: true,
            enumerable: true,
        };
        propDesc.get = propDesc.get || (function (this: any) { return this[privateKey] });

        const originalSetter = propDesc.set || (function (this: any, val: any) { this[privateKey] = val });

        propDesc.set = function (this: any, val: any) {
            let oldValue = this[key];
            if(val != oldValue) {
                originalSetter.call(this, val);
                let isNotFirstChange = this[isNotFirstChangePrivateKey];
                this[isNotFirstChangePrivateKey] = true;
                if(isOnChanges(this)) {
                    var changes: SimpleChanges = {
                        [key]: new SimpleChange(oldValue, val, !isNotFirstChange)
                    }
                    this.ngOnChanges(changes);
                }
            }
        }
        return propDesc;
    }
}

// Usage
export class MyClass implements OnChanges {

    //Properties what I want to track !
    @Watch()
    myProperty_1: boolean  =  true
    @Watch()
    myProperty_2 =  ['A', 'B', 'C'];
    @Watch()
    myProperty_3 = {};

    constructor() { }
    ngOnChanges(changes: SimpleChanges) {
        console.log(changes);
    }
}

var myInatsnce = new MyClass(); // outputs original field setting with firstChange == true
myInatsnce.myProperty_2 = ["F"]; // will be notified on subsequent changes with firstChange == false

原文由 Titian Cernicova-Dragomir 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题