如果@Input正在接收对象,则ngOnChanges不触发

时间:2019-03-07 17:50:51

标签: angular angular6 angular2-template

父组件模板:

<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不会触发。

如果我尝试使用二传手,它也不起作用:

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

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

显然,@Input()仅能检测对象的结构何时改变,而不是其值。

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

6 个答案:

答案 0 :(得分:2)

@Input属性值更改时,将触发OnChanges生命周期挂钩。对于对象,该值为对象引用。如果对象引用未更改,则不会触发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;
}

有关演示,请参见this stackblitz

答案 1 :(得分:1)

赞:

@Input() public param: any;
ngOnChanges(changes: SimpleChanges): void {
    // Do your check here
    console.log(changes.param.previousValue);
}

使用更改使您可以访问previousValue和currentValue。

答案 2 :(得分:1)

@Input属性值更改时,将触发角度更改检测。

因此,要在对象发生变化时触发更改检测,您可以 使用散布运算符 作为输入来传递对象的副本。

例如someVar = {key: value}这是@Input()变量,所以像

<app-sample [someVar]="{...someVar}" ></app-sample>

{...VARIABLE} <-这就是魔术

答案 3 :(得分:0)

我找到了基于富兰克林答案的解决方案:

只需创建一个返回对象副本的方法,例如

whateverCopy() {
    return {...this.whatever}
}

并通过

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

答案 4 :(得分:0)

您有参考 https://angular.io/guide/lifecycle-hooks#onchanges

<块引用>

日志条目显示为 power 属性的字符串值 变化。但是请注意,ngOnChanges() 方法不会捕获 更改为 hero.name。这是因为 Angular 仅在以下情况下调用钩子 输入属性的值发生变化。在这种情况下,英雄是 input 属性,而 hero 属性的值是对 英雄对象。对象引用的值不变时 它自己的名称属性已更改。

答案 5 :(得分:0)

我使用第二个@input 变量触发更改检测解决了这个问题:

def finder(arr,n,k):
    l2 = []
    arr.sort()
    for x in range(n-1,k,-1):
        l2.append(arr[x])
    return l2

查看:

export class MyViewComponent  {
  @Input() triggerChangeDetection: [];
  @Input() data: Data;

每次更新我调用的数据对象时:

<app-mycomponent [data]="data" [triggerChangeDetection]="triggerChangeDetection"></app-mycomponent >