为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 ngOnChanges() 在 @Input() 更新数据 Angular 8 时不会触发?

为什么 ngOnChanges() 在 @Input() 更新数据 Angular 8 时不会触发?

慕哥6287543 2022-11-27 16:06:27
父组件.html<parent-comp [data]="mydata"> </parent-comp>父组件.tsthis.service.abc$        .takeUntil(this.ngUnsubscribe.asObservable())        .subscribe((data: myType[]) => {            this.mydata= data;        });子组件.ts@Input data;在类下我有下面的代码public ngOnChanges() { if (this.data) { console.log(this.data); } }现在我希望每当我收到@Input data从父组件到子组件的最新数据时,我的ngOnChanges函数应该触发并在控制台中打印数据。但不幸ngOnChanges的是功能不会再次触发。仅在组件初始化时触发一次如果有人想要更多详细信息,请告诉我!谢谢!
查看完整描述

5 回答

?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

鉴于缺乏进一步的信息,我会做出有根据的猜测,@Input data它是一个数组或一个对象。


根据文档,ngOnChanges是:


当指令的任何数据绑定属性更改时调用的生命周期挂钩。


然而,它没有说明应该如何更改属性。一般来说,只有当对属性的引用发生更改时才会触发挂钩。


考虑以下例如。


父组件控制器


mydata = [];


updateMyData(value: any) {

  this.mydata.push(value);

}

父组件模板


<app-child [data]="mydata"></app-child>

子组件控制器


@Input() data: any;


ngOnChanges(changes: SimpleChanges) {

  console.log(changes);

}

现在您希望ngOnChanges每次updateMyData()在父组件中调用该函数时都会触发。但是对变量的引用mydata永远不会改变。所以钩子不会被触发。有多种方法可以强制更改检测器触发挂钩。


方法一:@Input将装饰器 绑定到setter,而不是直接绑定变量。已经在答案中讨论过。


方法二: 使用扩展语法在父组件中重新赋值变量。


父组件控制器


mydata = [];


updateMyData(value: any) {

  this.mydata = [...this.mydata, value];

}

您也可以对对象使用相同的方法。


查看完整回答
反对 回复 2022-11-27
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

感谢大家提供快速有效的解决方案。


我得到了解决方案,它与你们建议的不完全相同但相似。


在父组件中:


**Earlier I was assigning this way**

`this.mydata= data;`



**But now I am assigning in below way:**

`this.mydata= cloneDeep(data);`

注意:cloneDeep是从进口的lodash


查看完整回答
反对 回复 2022-11-27
?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

NgOnChanges 只会在原始类型的输入绑定属性更改时触发。这是因为必须更改对数据变量的引用才能注册更改,以便您可以在此生命周期挂钩中获取它。

因此,实现此目的的可能方法是更改“mydata”变量的引用。mydata = [...mydata]比如,如果 mydata 变量是一个数组,或者mydata = {...mydata}它是来自父组件的一个对象,当它被改变时,分配一个新的引用给 mydata 变量。


查看完整回答
反对 回复 2022-11-27
?
守着一只汪

TA贡献1872条经验 获得超4个赞

它可能是您传递的数据。如果它没有改变,那么 ngOnChanges 将不会注册任何更改。这是一个示例,您可以看到一个属性是否多次更改,然后它只会在第一次更新时触发,但如果您重新创建对象,它每次都会更改。(请参阅 stackblitz 中的控制台日志)


https://stackblitz.com/edit/angular-ivy-qmb35h?file=src%2Fapp%2Fapp.component.html


你可以像我一样做,每次都重新创建对象来绕过这个,或者更 hacky 的方法可能是保留一个你传递下来的虚拟“计数”变量,并在每次你想要子组件注册时递增它改变。


查看完整回答
反对 回复 2022-11-27
?
叮当猫咪

TA贡献1776条经验 获得超12个赞

您可以在角度中对@Input 使用setter 和getter 方法。请参考以下行以供参考:


private _data: any;

  @Input()

  set data(data) {

    this._data = data;

    console.log(this._data);

  };

仅从 setter 方法,您也可以调用任何其他方法,并且可以从那里运行您想要的任何逻辑。


查看完整回答
反对 回复 2022-11-27
  • 5 回答
  • 0 关注
  • 232 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号