Angular创建新数组条目时所有已有对象同步变更问题
问题现象
通过HTML表单创建新条目时,新条目可正常展示,但每次创建新条目后,之前已创建的条目内容会同步发生变更。如果启用注释中的index去重判断逻辑,仅能成功创建1个对象,无法继续创建后续条目。
相关代码如下:
position.ts
export interface Position{ index:number; lat: number; lng: number; time: string; }
positions.component.ts
import { Component, OnInit } from '@angular/core'; import { Positions } from '../mock-positions'; @Component({ selector: 'app-positions', templateUrl: './positions.component.html', styleUrls: ['./positions.component.css'] }) export class PositionsComponent implements OnInit { constructor() { } positionEntrys = 'Positions '; positions= Positions; ngOnInit(): void { } }
create-poistion.component.ts
import { Component, OnInit } from '@angular/core'; import { Position } from '../position'; import { Positions } from '../mock-positions'; @Component({ selector: 'app-create-position', templateUrl: './create-position.component.html', styleUrls: ['./create-position.component.css'] }) export class CreatePositionComponent implements OnInit { constructor() { } position: Position={ index: Positions.length, lat: -1, lng: -1, time: "testdata", } ngOnInit(): void { } save() : void{ Positions.push(this.position) //var postionByTimestamp= Positions.find(x => x.index ==this.position.index); //if(postionByTimestamp==null || postionByTimestamp==undefined){ //Positions.push(this.position) //} //else{ //postionByTimestamp=this.position //} } }
原因分析
两个核心问题导致异常:
- 对象引用复用:组件属性
position是组件初始化时创建的单个对象,每次调用save()往数组push的都是同一个对象的引用,没有生成新对象。后续表单修改this.position的属性值时,数组中所有已存入的条目因为指向同一块内存地址,内容会同步被修改,表现为旧条目跟着新条目一起变。 - index只初始化一次:
position.index仅在组件初始化时赋值为当时的Positions.length,后续新增条目时不会重新计算。启用去重逻辑后,第一次保存后数组中已存在对应index的条目,后续每次保存查找都能匹配到重复index,不会执行push逻辑,自然只能创建1个条目。
另外注释中的更新逻辑存在错误:postionByTimestamp是find返回的局部变量,直接给该变量赋值不会修改原数组中的对象,仅会改变局部变量的指向。
修复方法
修改create-poistion.component.ts中的save方法,每次保存时创建全新的Position对象,实时计算新条目的index,保存完成后重置表单绑定的对象即可:
save() : void{ // 每次保存生成全新对象,切断引用关联 const newPosition: Position = { index: Positions.length, // 每次保存时实时取最新数组长度作为index lat: this.position.lat, lng: this.position.lng, time: this.position.time } Positions.push(newPosition) // 保存后重置表单对象,方便下一次录入 this.position = { index: Positions.length, lat: -1, lng: -1, time: "testdata", } }
如果需要保留index去重判断逻辑,注意要在计算完新index后执行判断,更新已有条目时直接修改对象属性,不要给局部变量重新赋值:
save() : void{ const targetIndex = Positions.length; const existItem = Positions.find(x => x.index === targetIndex); const newPosition: Position = { index: targetIndex, lat: this.position.lat, lng: this.position.lng, time: this.position.time } if (!existItem) { Positions.push(newPosition) } else { // 直接修改原对象属性,不要给局部变量赋值 existItem.lat = newPosition.lat; existItem.lng = newPosition.lng; existItem.time = newPosition.time; } // 重置表单 this.position = { index: Positions.length, lat: -1, lng: -1, time: "testdata", } }
内容的提问来源于stack exchange,提问作者fsf sdfsdf
相关产品推荐
相关产品推荐

