簡體   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