尝试传递新对象时不会触发 ngOnChanges 子方法
ngOnChanges child method is not triggering when attempting to pass a new object
我有一个将 user
数据传递给子组件的父页面,如下所示:
<ng-container *ngIf="leaderboard">
<app-leaderboard-preview [user]="user" (click)="goToLeaderboard()"></app-leaderboard-preview>
</ng-container>
父页面 ngOnInit()
订阅了一个 returns 用户对象的可观察对象并设置了 user
变量(我从 combineLatest
中删除了其他不相关的查询):
combineLatest([this.userQuery$]).subscribe((results) => {
Promise.all([this.parseUser(results[4])])
})
据我了解,除非创建新对象,否则 ngOnChanges()
不会触发,因此我将新用户对象分配为新对象,以使用 [=20] 传递给 app-leaderboard-preview
组件=]
parseUser(user) {
return new Promise((resolve) => {
if(user) {
this.user = Object.assign({}, user);
resolve(user);
} else {
resolve(user);
}
})
}
这加载了组件,很好,但是用户的排名可以改变,所以当用户向下滑动刷新页面时,值应该更新,但组件没有更新。我使用以下代码(几乎是上面的副本)来刷新页面(无需硬重新加载)。
doRefresh(event) {
if (this.user) {
//user
this.userQuery$ = this.db.query$(`user/find?id=${this.user.id}`);
combineLatest([this.userQuery$]).subscribe((results) => {
Promise.all([this.parseUser(results[4])])
})
}
然后运行 parseUser
方法来更新 app-leaderboard-preview
使用的 user
对象。
所以这应该会触发 ngOnChanges,因为我正在将 "new" 对象传递给组件。我错过了什么?
我以前 运行 遇到过同样的问题,想知道是否有人知道如何解决它。
我绕过它的方法是像这样在我的输入变量上使用 get() set() 方法。这不是一个很好的解决方案,尤其是当您有多个输入变量时。
private _user: any;
@Input()
set user(value: any) {
this._user = value;
// run ngOnChanges stuff here
this.ngOnChanges();
}
get user(): any {
return this._user;
}
编辑
经过一番折腾,Jordan 发现他有一个异步管道分配给用户变量,该变量覆盖了他对 this.user 的更改。
*ngIf = user$ | async as user
原答案
Object.assign({}, object) 应该有效。在 Angular 7.
上测试
this.user = Object.assign({}, user);
.. 或者如果你使用的是 lodash,你可以这样做。
this.user = _.clone(user);
this.user = _.cloneDeep(user);
https://lodash.com/docs/4.17.11#clone
https://lodash.com/docs/4.17.11#cloneDeep
Stackblitz 演示:
https://stackblitz.com/edit/ngonchangeswithobject
我有一个将 user
数据传递给子组件的父页面,如下所示:
<ng-container *ngIf="leaderboard">
<app-leaderboard-preview [user]="user" (click)="goToLeaderboard()"></app-leaderboard-preview>
</ng-container>
父页面 ngOnInit()
订阅了一个 returns 用户对象的可观察对象并设置了 user
变量(我从 combineLatest
中删除了其他不相关的查询):
combineLatest([this.userQuery$]).subscribe((results) => {
Promise.all([this.parseUser(results[4])])
})
据我了解,除非创建新对象,否则 ngOnChanges()
不会触发,因此我将新用户对象分配为新对象,以使用 [=20] 传递给 app-leaderboard-preview
组件=]
parseUser(user) {
return new Promise((resolve) => {
if(user) {
this.user = Object.assign({}, user);
resolve(user);
} else {
resolve(user);
}
})
}
这加载了组件,很好,但是用户的排名可以改变,所以当用户向下滑动刷新页面时,值应该更新,但组件没有更新。我使用以下代码(几乎是上面的副本)来刷新页面(无需硬重新加载)。
doRefresh(event) {
if (this.user) {
//user
this.userQuery$ = this.db.query$(`user/find?id=${this.user.id}`);
combineLatest([this.userQuery$]).subscribe((results) => {
Promise.all([this.parseUser(results[4])])
})
}
然后运行 parseUser
方法来更新 app-leaderboard-preview
使用的 user
对象。
所以这应该会触发 ngOnChanges,因为我正在将 "new" 对象传递给组件。我错过了什么?
我以前 运行 遇到过同样的问题,想知道是否有人知道如何解决它。
我绕过它的方法是像这样在我的输入变量上使用 get() set() 方法。这不是一个很好的解决方案,尤其是当您有多个输入变量时。
private _user: any;
@Input()
set user(value: any) {
this._user = value;
// run ngOnChanges stuff here
this.ngOnChanges();
}
get user(): any {
return this._user;
}
编辑
经过一番折腾,Jordan 发现他有一个异步管道分配给用户变量,该变量覆盖了他对 this.user 的更改。
*ngIf = user$ | async as user
原答案
Object.assign({}, object) 应该有效。在 Angular 7.
上测试this.user = Object.assign({}, user);
.. 或者如果你使用的是 lodash,你可以这样做。
this.user = _.clone(user);
this.user = _.cloneDeep(user);
https://lodash.com/docs/4.17.11#clone
https://lodash.com/docs/4.17.11#cloneDeep
Stackblitz 演示: https://stackblitz.com/edit/ngonchangeswithobject