首页 > 解决方案 > 如果@Input 正在接收对象,ngOnChanges 不会触发

问题描述

父组件模板:

<my-component [param]="whatever"></my-component>

父组件代码:

whatever = { value1: 0, value2: 1, value3: 'foo' };

子组件代码:

@Input() public param: any;

ngOnChanges() {
  console.log('Received input: ', param);
}

这是行不通的。任何更改whatever都不会被子组件注意到并且ngOnChanges不会触发。

如果我尝试使用 setter,它也不起作用:

@Input() set param(value) {
  console.log(value);
}

如果我尝试在父组件中运行手动区域更新,它也无济于事。

显然@Input()只能检测到对象的结构何时发生了变化,而不能检测到它的值。

那么如何将对象作为@Input()属性传递并让子组件检测值变化呢?

标签: angularangular6angular2-template

解决方案


OnChanges生命周期挂钩在@Input属性值更改时触发。在对象的情况下,该值是对象引用。如果对象引用没有改变,OnChanges则不会触发。

强制更改检测的一种可能技术是在修改属性值后设置新的对象引用:

this.whatever.value1 = 2;
this.whatever.value2 = 3;
this.whatever = Object.assign({}, this.whatever);

然后ngOnChanges可以使用事件处理程序来监视更改:

ngOnChanges(changes: SimpleChanges) {
  for (let propName in changes) {
    let chng = changes[propName];
    let cur = JSON.stringify(chng.currentValue);
    console.log(propName, cur);
  }
}

作为替代方案,如果@Input装饰 getter/setter 属性,则可以在 setter 中监视更改:

private _param: Object;

@Input() get param(): Object {
  return this._param;
} 
set param(value: Object) {
  console.log("setter", value);
  this._param = value;
}

请参阅此 stackblitz以获取演示。


推荐阅读