【问题标题】:Change detection not working for complex objects used in NgFor更改检测不适用于 NgFor 中使用的复杂对象
【发布时间】:2019-01-31 04:15:16
【问题描述】:

我正在使用 Angular 7。我有一个父组件,它从 api 获取用户模型列表。当“get”成功时,它与 ngFor 循环结合使用,使用 @input 将每个用户注入到一个子组件中,该子组件将显示用户列表。

更新单个用户模型上的属性时,子组件不会反映此更改。我明白为什么会这样。我知道只有在列表中的引用发生更改时才会启动更改检测。但是我不知道如何解决这个问题。我尝试将用户模型数组实现为可观察对象并使用异步管道,该管道用于显示数据,但在进行更改时不起作用。

在我的具体示例中,我的用户模型上有一个“selected”属性,我的父组件上有一个“全选”按钮,我想用它来更改所有用户的“selected”属性在我的数组中,然后在 UI 上显示它。这是我的代码的一个非常简单的版本

export class ParentComponent {
users: UserModel[];

    ngOnInit() {
       this.userService.getUsers().subscribe(users => {
        this.users = users;
       });
    }

    onSelectAll() {
        for (let user of this.users) {
            user.selected  = true;
        }
    }
}

父组件在模板中有以下内容:

<tr users-item [index]="i + 1" [user]="user" *ngFor="let user of users; let i = index"></tr>

这是使用用户模型显示数据的子组件:

export class ChildComponent {
    @Input() user: UserModel;

    firstname: string;
    lastname: string;
    selected: boolean;

    ngOnChanges() {
        if (this.user) {
            this.firstname = this.user.firstname;
            this.lastname = this.user.lastname;
            this.selected = this.user.selected;
        }
    }
 }

和子组件模板:

<td><input type="checkbox" [checked]="selected"></td>
<td>{{ fullname }}</td>
<td>{{ lastname }}</td>

【问题讨论】:

  • 尝试将&lt;input type="checkbox" [checked]="selected"&gt; 更改为&lt;input type="checkbox" [checked]="user.selected"&gt; 或在stackblitz 上复制您的问题并分享链接

标签: angular ngfor angular2-changedetection


【解决方案1】:

您可以简单地坚持基于不变性的方法并创建具有更新属性的浅拷贝,而不是改变源对象。

在您的用例中,您可以通过更改全选的实现来做到这一点:

onSelectAll() {
    this.users = this.users.map(user => this.mergeUser(user, {selected: true}));
}

private mergeUser(source: UserModel, updated: Partial<UserModel>): UserModel{
   return {...source, ...updated};
}

【讨论】:

  • 谢谢先生。它不仅像魅力一样起作用,而且还教会了我一些关于 angular/typescript 的知识。
【解决方案2】:

以下部分代码无法理解。为什么要在 Table Row 中传递输入?

<tr users-item [index]="i + 1" [user]="user" *ngFor="let user of users; let i = index"></tr>

并且输入的变化可以被子组件的 SimpleChanges 捕获。你应该试试这样的。

  ngOnChanges(changes: SimpleChanges) {
        if (changes.user && changes.user.currentValue) {
            this.firstname = changes.user.currentValue.firstname;
            this.lastname = changes.user.currentValue.lastname;
            this.selected = changes.user.currentValue.selected;
        }
    }

【讨论】:

  • 因为一旦所有内容都被渲染,它将被渲染为行和列。同样使用 SimpleChanges 也不会产生任何影响,因为 ngOnChanges 仅在更改检测启动时注册。更改检测仅在引用更改时启动。
猜你喜欢
  • 1970-01-01
  • 2021-02-25
  • 2019-09-16
  • 1970-01-01
  • 2020-10-04
  • 2021-01-06
  • 1970-01-01
  • 2020-10-31
  • 2019-11-06
相关资源
最近更新 更多