繁体   English   中英

Angular:我在 @input 中将 ngmodel 从父级传递给子级; 改变对应@input的值,更新parent中的值

[英]Angular: I am passing ngmodel in a @input from parent to child; change the value of corresponding @input, the value in parent is updated

Angular:我在 @input 中将 ngmodel 从父级传递给子级; 当我更改子项中相应@input 的值时,父项中的值也会更新,导致它的行为类似于 2 路绑定。谁能解释为什么会这样

父 html:

<app-config-form [data]="param"></app-config> //param is ngModel

child.ts:

@Input() data:any = {}

您描述的行为发生在输入不是原始类型(数字/字符串/布尔值)时。 If it's a complex object (different from null ) and you change any property of the object, that change will reflect on the parent's object, because it's the same: you're dealing with references, not with values.

如果您想避免这种情况,您必须对输入进行深度克隆,如下所示:

private _data: any;
@Input() set data(d: any) {
  // If you want to improve performance, use this library to do a deep clone:
  // https://github.com/planttheidea/fast-copy
  // otherwise, you can go with JSON.parse(JSON.sringify(...))

  this._data = d ? JSON.parse(JSON.sringify(d)) : null;
}
get data(): any {return this._data;}

补充资料

现在,作为信息:如果您愿意,可以真正使用 2-way 数据绑定:

@Input() data:any = {}

// mandatory: the same name of the @Input, suffixed with "Change"
@Ouput() dataChange = new EventEmitter<any>();

然后,您可以在父级中使用“banana-in-the-box”表示法:

<app-config-form [(data)]="param"></app-config> //param is ngModel

但更新不会自动触发。 每次在孩子中更改它时,都必须调用this.dataChange.emit(value)

例如(在孩子身上):

buttonClickHandler() {
  this.data = 2;
  this.dataChange.emit(2);
}

您正在使用[(ngModel)] 这意味着您需要两种方式的数据绑定。 当您更改与[(ngModel)]关联的值时,它会在您使用它的所有地方做出反应。 因此,如果您在该变量处不需要ngmodel ,请使用替代方式。

您需要在您的孩子中创建数据副本:

@Input() data:any = {}
childData: any;


OnInit() {
   this.childData = JSON.parse(JSON.stringify(this.data));
}

这将让您修改 childData 避免父组件中的更新,因为 childData 是另一个 object 而不是数据。 在您的示例中,您将 object 从父级传递给子级,但实际上是相同的 object 并且因此,当您在子级中更新它时,它会在父级中更新。

对象是可变

可变是一种可以更改的变量。 在 JavaScript 中,只有对象和 arrays 是可变的,而不是原始值。

这就是为什么值会发生变化......关于js中的不变性有一篇很好的文章

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM