简体   繁体   English

angular10:如何在数组更改中检测复杂输入 object

[英]angular10: How to detect complex input object in array change

I have an array that I use DoCheck and IterableDiffer to listen to changes in my code.我有一个数组,我使用 DoCheck 和 IterableDiffer 来监听我的代码中的变化。 When the array is changed, but when a property inside one of the objects in the array changes I don't get notified.当数组更改时,但当数组中的一个对象内的属性更改时,我不会收到通知。 I tried using KeyValueDiffer for each object in the array types but it doesn't work in ngDoCheck .我尝试对数组types中的每个 object 使用 KeyValueDiffer ,但它在ngDoCheck中不起作用。 Any ideas?有任何想法吗?

In the parent:在父级中:

<comp [types]="types"></comp>
readonly: boolean =  false;

types: {
  readonly: boolean;
  title: string;
  value: any;
}[] = [{
  title: 'title1',
  readonly: this.readonly,
  value: 1
}, {
  title: 'title2',
  readonly: this.readonly,
  value: 2
}];

ngOnInit() {
    setTimeout(() => {
      this.readonly = true;
    }, 5000)
}

In component comp :在组件comp中:

constructor(
    private differsService: KeyValueDiffers
) {};

@Input types: any[] = [];

ngOnInit() {
    this.differ = this.searchTypes.reduce((t, c, i) => {
      t[`types_${i}`] = this.differsService.find(c).create();
      return t;
    }, {});
}

ngDoCheck(): void {
    if (this.differ) {
      Object.keys(this.differ).map((key: string) => {
        const k = key.split('_');
        const state = k.length === 1?this[k[0]]:this[k[0]][k[1]];
        const changes = this.differ[key].diff(state);
        if (changes) {
          console.log(key, changes);
        }
      })
    }  
}

In Angular, change detection is triggered on assignment.在 Angular 中,更改检测在分配时触发。 This means that you need to assign new value to bound variables or objects to trigger the change detection.这意味着您需要为绑定的变量或对象分配新值以触发更改检测。 So, instead of changing properties on objects only.因此,而不是仅更改对象的属性。 Try to reassign the array again afterwards to trigger detection:之后尝试重新分配数组以触发检测:

types = [...types];

Try assigning that in the parent component when updating the values in types array在更新类型数组中的值时尝试在父组件中分配它

<comp [types]="types"></comp>

This article might help you in understanding that concept: https://www.digitalocean.com/community/tutorials/angular-change-detection-strategy本文可能会帮助您理解该概念: https://www.digitalocean.com/community/tutorials/angular-change-detection-strategy

First point to be made is that this kind of change detection can be unnecessarily expensive and complicated.首先要指出的是,这种变化检测可能会不必要地昂贵和复杂。 I'd recommend reading up on RxJS and how it works to handle changes in data.我建议阅读 RxJS 以及它如何处理数据变化。

In your specific example, however, the problem is not with your key differs, but with the logic of how you're handling readonly但是,在您的具体示例中,问题不在于您的密钥不同,而在于您如何处理readonly的逻辑

In javascript, primitives (such as booleans) are not passed by reference, but by value.在 javascript 中,原语(例如布尔值)不是通过引用传递,而是通过值传递。

This means that when you set the following:这意味着当您设置以下内容时:

readonly: this.readonly

the value in the type for readonly is set to false, and that's it. readonly type中的值设置为 false,仅此而已。 If later you change this.readonly the value within type is not changed.如果稍后您更改this.readonly ,则type中的值不会更改。 If you want to keep the connection between the two "live", you need to pass by reference, with an object, for example.如果要保持两个“实时”之间的连接,则需要通过引用传递,例如 object。 something like就像是

this.readonly = { status: false }

Then when you do然后当你这样做

this.readonly.status = true

that value will be changed in the types as well.该值也将在types中更改。

Here's a stackblitz demonstrating it in action (and no need for keydiffers):这是一个 stackblitz 演示它的实际操作(并且不需要 keydiffers):

https://stackblitz.com/edit/angular-ivy-d8gige?file=src/app/app.component.ts https://stackblitz.com/edit/angular-ivy-d8gige?file=src/app/app.component.ts

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM