[英]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: I am passing ngmodel in a @input from parent to child; Angular:我在 @input 中将 ngmodel 从父级传递给子级; When i change the value of corresponding @input in child the value in parent is also updated causing it to behave like 2 way binding.Can anyone explain why is it so当我更改子项中相应@input 的值时,父项中的值也会更新,导致它的行为类似于 2 路绑定。谁能解释为什么会这样
parent html:父 html:
<app-config-form [data]="param"></app-config> //param is ngModel
child.ts: child.ts:
@Input() data:any = {}
The behavior you're describing happens when the input isn't a primitive type (number/string/boolean).您描述的行为发生在输入不是原始类型(数字/字符串/布尔值)时。 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. 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.
You must do a deep clone of the input if you want to avoid this situation, like this:如果您想避免这种情况,您必须对输入进行深度克隆,如下所示:
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;}
Now, as info: to really use the 2-way data binding if you'd like to:现在,作为信息:如果您愿意,可以真正使用 2-way 数据绑定:
@Input() data:any = {}
// mandatory: the same name of the @Input, suffixed with "Change"
@Ouput() dataChange = new EventEmitter<any>();
Then you can use, in the parent, the "banana-in-the-box" notation:然后,您可以在父级中使用“banana-in-the-box”表示法:
<app-config-form [(data)]="param"></app-config> //param is ngModel
But the update is not automatically fired.但更新不会自动触发。 Every time you change it in the child, you must call this.dataChange.emit(value)
.每次在孩子中更改它时,都必须调用this.dataChange.emit(value)
。
For example (in the child):例如(在孩子身上):
buttonClickHandler() {
this.data = 2;
this.dataChange.emit(2);
}
You are using [(ngModel)]
.您正在使用[(ngModel)]
。 It means that you want two way data binding.这意味着您需要两种方式的数据绑定。 When you change the value associated with [(ngModel)]
, it would react at all where you use it.当您更改与[(ngModel)]
关联的值时,它会在您使用它的所有地方做出反应。 So use alternate way if you don't have required ngmodel
at that variabel.因此,如果您在该变量处不需要ngmodel
,请使用替代方式。
You need to create a copy of data in your child:您需要在您的孩子中创建数据副本:
@Input() data:any = {}
childData: any;
OnInit() {
this.childData = JSON.parse(JSON.stringify(this.data));
}
This will let you modify childData avoiding updates in parent component, because childData is another object than data.这将让您修改 childData 避免父组件中的更新,因为 childData 是另一个 object 而不是数据。 In your example, you pass the object from parent into child, but in fact, is the same object and due of this, when you update it in child, this is updated in parent.在您的示例中,您将 object 从父级传递给子级,但实际上是相同的 object 并且因此,当您在子级中更新它时,它会在父级中更新。
Mutable is a type of variable that can be changed.可变是一种可以更改的变量。 In JavaScript, only objects and arrays are mutable, not primitive values.在 JavaScript 中,只有对象和 arrays 是可变的,而不是原始值。
This is why value changes... There is a good article about immutability in js这就是为什么值会发生变化......关于js中的不变性有一篇很好的文章
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.