父组件模板:
<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属性值更改时会触发角度变化检测。
因此,要在对象的情况下触发更改检测,您可以使用spread运算符作为输入传递对象的副本。
例如。 someVar = {key: value}
这是@Input()
变量,所以传球就好
<app-sample [someVar]="{...someVar}" ></app-sample>
{...VARIABLE}
当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。
像这样:
@Input() public param: any;
ngOnChanges(changes: SimpleChanges): void {
// Do your check here
console.log(changes.param.previousValue);
}
使用更改可以访问previousValue和currentValue。