0

我有一个与以下代码相关的问题:

孩子

export class ChildComponent implements OnChanges {
    public @Input() data: string[];

    ngOnChanges(changes: SimpleChanges) {
        console.log('I am here');
    }
}

子模板

{{ data | json }} // This is not necessary. The behaviour is the same with or without it.

<div *ngFor="let item of data">
    {{ item }}
</div>

家长

export class AppComponent implements OnInit {
    public test: string[] = ['hello'];

    ngOnInit() {
        console.log('I am here');
    }

    public addItem() {
        this.test.push('sample');
    }
}

父模板

<child-component [data]="test"></child-component>
<button (click)="addItem()">Add</button>

我知道只有在数组引用发生更改时才会调用 ngOnChanges,如果我将元素推送到数组中,它将不会被调用。以下引起了我的注意。当我按下添加按钮时,一个新元素被添加到数组中并且视图被正确更新。我使用 json 管道和 ngFor 来证明它更新正确。如果我不使用 json 管道,行为是一样的。那么,如果视图更新正确,为什么不调用 ngOnChanges 呢?谁负责检测是否有更改以在视图中显示?

综上所述,疑点如下。为什么当一个元素被添加到数组中时,视图会正确更新,但为什么没有调用 ngOnChanges?

变化检测的方式不同?

4

1 回答 1

2

您可能很清楚ngOnChanges,它是为处理@Input()属性的任何更改而设计的(以防将新数据简单地提供给组件可能会产生一些额外的影响,并且不能通过组合setand来完成@Input())。所以它只关注@Input()变化。此外,正如您所知道的,只有在参考即将更改时才会更新。

并且您的组件无论如何都会更新,因为:

  • 您并没有告诉组件仅使用OnPush更改检测策略(因此它不仅会更改任何@Input()或任何可观察/事件的参考更改)
  • 此外(这是这里的关键)您的子视图中有一个不纯的管道。在这里,我发现了一些关于脏管道的问题,我认为它应该回答你的问题:链接(因为json管道是不纯的 -文档)。尝试删除它,看看会发生什么。

请接受这只是一个理论的事实。但我很确定这是对的。

编辑:哦,这里的官方文档中似乎有一个完美的例子:

...当你添加英雄时,飞行英雄会显示更新,即使你改变了英雄数组。

于 2020-03-04T16:59:33.003 回答