为啥 Angular 2 ngOnChanges 不响应输入数组推送

Posted

技术标签:

【中文标题】为啥 Angular 2 ngOnChanges 不响应输入数组推送【英文标题】:Why angular 2 ngOnChanges not responding to input array push为什么 Angular 2 ngOnChanges 不响应输入数组推送 【发布时间】:2017-08-30 14:51:16 【问题描述】:

我的 Angular 应用程序遇到了一个问题,我将输入用作数组,并在单击事件发生时将值推送到数组。但是当数组推送完成时 ngOnChanges 不会触发。有没有办法触发 ngOnChange

我的代码是 ts 文件是

@Component(
  selector: 'adv-search',
  templateUrl: './app/modules/result.html'
)

export class InputComponent 
  @Input() metas:any=[];

  ngOnChanges() 
    console.log(this.metas);
  

我的选择器标签

<adv-search [metas] = "metaIds"></adv-search>

点击事件代码

insertIds(id:any) 
   metaIds.push(id);

【问题讨论】:

你在哪里使用过insterIds事件? 您在主组件或子组件中更改数组? 【参考方案1】:

角度变化检测仅检查对象身份,而不检查对象内容。 因此不会检测到插入或删除。

你可以做的是在每次更新后复制数组

insertIds(id:any) 
  this.metaIds.push(id);
  this.metaIds = this.metaIds.slice();

或使用IterableDiffer 来检查ngDoCheckInputComponent 内部的变化,就像NgFor 一样。

【讨论】:

这里的复制数组是什么意思? 该数组将是另一个(另一个对象实例)但具有原始内容。 Angular 会识别这种变化。 你确定这样做 Angular 会识别出这些变化吗? @PardeepJain 谢谢你的提示,没注意。更新了我的答案。 在 Angular 中没有类似的东西,主要是出于性能原因。最好的方法通常是在对象中有一个 Observable 并在你想要得到通知的地方订阅它。对于数组,有angular.io/api/core/IterableDiffers。使用方法可以查看*ngFor的来源。【参考方案2】:

如果您重新分配 metaIds 数组,则会触发 ngOnChanges 生命周期事件。您可以将数组解构为一个新数组。

insertIds(id:any)
    this.metaIds = [...this.metaIds, id];

【讨论】:

【参考方案3】:

@GünterZöchbauer 的回答是完全正确的。但是,我想添加一个替代/补充来复制整个数组。使用问题中的相同示例。

<adv-search [metas] = "metaIds"></adv-search>

改成

<adv-search [metas] = "trackBy: metaIds.length, metaIds: metaIds"></adv-search>

这里的长度相当于组件的 *ngFor trackBy 函数。这样,ngOnChanges 就会随着内容长度的变化而发生。

如果与 *ngFor trackBy 方法结合使用,应该会有一些性能优势,因为不会重新计算整个数组的绑定模板(没有屏幕/内容闪烁)。

【讨论】:

以上是关于为啥 Angular 2 ngOnChanges 不响应输入数组推送的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 2 上实现 ngOnChanges 以进行输入验证,而不触发“检查后表达式已更改。”错误

Angular ngOnChanges 和变化检测策略似乎是矛盾的?

IONIC2/Angular2 ngOnChange 不起作用

Angular ngOnchanges 调用方法,但方法不调用服务或输出结果

在 Angular 4 中,钩子 ngOnChanges 不会在输入时触发

Angular Lifecycle Interface OnChanges 应该为方法 ngOnChanges 实现