如果 @Input 正在接收对象,则 ngOnChanges 不会触发
ngOnChanges not firing if an @Input is receiving an object
父组件模板:
<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()
属性 传递并让子组件检测值变化?
像这样:
@Input() public param: any;
ngOnChanges(changes: SimpleChanges): void {
// Do your check here
console.log(changes.param.previousValue);
}
使用更改可以访问 previousValue 和 currentValue。
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;
}
有关演示,请参阅 this stackblitz。
Angular 当@Input 属性 值改变时触发变化检测。
因此,要在对象的情况下触发更改检测,您可以 使用扩展运算符 作为输入传递对象的副本。
例如。 someVar = {key: value}
这是 @Input()
变量,所以传递 like
<app-sample [someVar]="{...someVar}" ></app-sample>
{...VARIABLE}
<- 这就是魔法
如果扩展运算符不起作用,请使用任何对象深度复制方法,例如
JSON.parse(JSON.stringify(obj))
我找到了基于富兰克林答案的解决方案:
只需创建一个方法,其中returns对象的副本,如
whateverCopy() {
return {...this.whatever}
}
并点赞
<my-component [param]="whateverCopy"></my-component>
你有参考 https://angular.io/guide/lifecycle-hooks#onchanges
The log entries appear as the string value of the power property
changes. Notice, however, that the ngOnChanges() method does not catch
changes to hero.name. This is because Angular calls the hook only when
the value of the input property changes. In this case, hero is the
input property, and the value of the hero property is the reference to
the hero object. The object reference did not change when the value of
its own name property changed.
我使用第二个@input 变量触发变化检测解决了这个问题:
export class MyViewComponent {
@Input() triggerChangeDetection: [];
@Input() data: Data;
查看:
<app-mycomponent [data]="data" [triggerChangeDetection]="triggerChangeDetection"></app-mycomponent >
每次更新我调用的数据对象时:
export class AppComponent{
public data: Data;
public triggerChangeDetection: [];
private triggerChangeDetectionToUpdateComponents() {
this.triggerChangeDetection = [];
}
父组件模板:
<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()
属性 传递并让子组件检测值变化?
像这样:
@Input() public param: any;
ngOnChanges(changes: SimpleChanges): void {
// Do your check here
console.log(changes.param.previousValue);
}
使用更改可以访问 previousValue 和 currentValue。
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;
}
有关演示,请参阅 this stackblitz。
Angular 当@Input 属性 值改变时触发变化检测。
因此,要在对象的情况下触发更改检测,您可以 使用扩展运算符 作为输入传递对象的副本。
例如。 someVar = {key: value}
这是 @Input()
变量,所以传递 like
<app-sample [someVar]="{...someVar}" ></app-sample>
{...VARIABLE}
<- 这就是魔法
如果扩展运算符不起作用,请使用任何对象深度复制方法,例如
JSON.parse(JSON.stringify(obj))
我找到了基于富兰克林答案的解决方案:
只需创建一个方法,其中returns对象的副本,如
whateverCopy() {
return {...this.whatever}
}
并点赞
<my-component [param]="whateverCopy"></my-component>
你有参考 https://angular.io/guide/lifecycle-hooks#onchanges
The log entries appear as the string value of the power property changes. Notice, however, that the ngOnChanges() method does not catch changes to hero.name. This is because Angular calls the hook only when the value of the input property changes. In this case, hero is the input property, and the value of the hero property is the reference to the hero object. The object reference did not change when the value of its own name property changed.
我使用第二个@input 变量触发变化检测解决了这个问题:
export class MyViewComponent {
@Input() triggerChangeDetection: [];
@Input() data: Data;
查看:
<app-mycomponent [data]="data" [triggerChangeDetection]="triggerChangeDetection"></app-mycomponent >
每次更新我调用的数据对象时:
export class AppComponent{
public data: Data;
public triggerChangeDetection: [];
private triggerChangeDetectionToUpdateComponents() {
this.triggerChangeDetection = [];
}