Angular: я передаю ngmodel в @input от родителя к ребенку; изменить значение соответствующего @input, значение в parent обновляется - PullRequest
0 голосов
/ 03 апреля 2020

Angular: я передаю ngmodel в @input от родителя к ребенку; Когда я изменяю значение соответствующего @input в child, значение в parent также обновляется, в результате чего оно ведет себя как двухстороннее связывание. Может кто-нибудь объяснить, почему так

parent html:

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

child.ts:

@Input() data:any = {}

Ответы [ 4 ]

0 голосов
/ 03 апреля 2020

Объекты изменяемые

Изменяемые - это тип переменной, которую можно изменить. В JavaScript только объекты и массивы являются изменяемыми, а не примитивными значениями.

Именно поэтому значения меняются ... Есть хорошая статья о неизменности в js

0 голосов
/ 03 апреля 2020

Вы используете [(ngModel)]. Это означает, что вы хотите двухстороннее связывание данных. При изменении значения, связанного с [(ngModel)], оно будет реагировать на все, где вы его используете. Поэтому используйте альтернативный способ, если вам не требуется ngmodel для этой переменной.

0 голосов
/ 03 апреля 2020

Вам необходимо создать копию данных в вашем потомке:

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


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

Это позволит вам изменять childData, избегая обновлений в родительском компоненте, потому что childData - это другой объект, чем данные. В вашем примере вы передаете объект из parent в child, но на самом деле это тот же объект, и поэтому при обновлении его в child он обновляется в parent.

0 голосов
/ 03 апреля 2020

Поведение, которое вы описываете, происходит, когда ввод не является примитивным типом (число / строка / логическое значение). Если это сложный объект (отличный от null), и вы изменяете любое свойство объекта, это изменение отразится на родительском объекте, потому что оно одинаково: вы имеете дело со ссылками, а не со значениями.

Вы должны сделать глубокое клонирование ввода, если хотите избежать этой ситуации, например:

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- способ привязки данных, если вы хотите:

@Input() data:any = {}

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

Тогда вы можете использовать в родительской нотации «банан в коробке»:

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

Но обновление не запускается автоматически. Каждый раз, когда вы меняете его у ребенка, вы должны звонить this.dataChange.emit(value).

Например (у ребенка):

buttonClickHandler() {
  this.data = 2;
  this.dataChange.emit(2);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...