我正在开发一个angular2应用程序,利用多个服务在整个应用程序中共享日期。
在我的应用程序的一部分中,我有一个编辑功能,允许用户修改数组中的数据。
在这种情况下,当用户修改组件中的属性时,也会修改服务中的相应数据而不直接设置它。
我大约有6个月学习角度,但我知道将一个数组设置为另一个数组实际上是指向同一个对象。所以在这种情况下,我在服务中有一个方法将数组作为slice()返回,我认为应该创建新的数组以避免用户能够直接修改服务数据。
我正在处理的完整应用程序相当复杂,但我能够创建一个简单的角度应用程序来演示正在发生的事情。
<div *ngFor="let item of testComponentData">
<p>{{ item.fname }} {{ item.lname }} <button (click)="onUpdate(item.id)">Update</button></p>
</div>
export class TestObject {
constructor(public id: string, public fname: string, public lname: string) {}
@Injectable()
export class TestService {
constructor() { }
private serviceData: TestObject[] = [
new TestObject('1', 'Joe', 'Smith'),
new TestObject('2', 'Mary', 'Jones'),
new TestObject('3', 'Larry', 'Murray'),
];
getData() {
return this.serviceData.slice();
}
}
export class TestComponent implements OnInit {
testComponentData: TestObject[];
constructor(private testService: TestService) { }
ngOnInit() {
this.testComponentData = this.testService.getData();
}
onUpdate(id) {
// Clicked 3rd button, id = 3
const temp = this.testComponentData.find(o => o.id === id);
console.log(this.testService.getData());
// 0: TestObject {id: "1", fname: "Joe", lname: "Smith"}
// 1: TestObject {id: "2", fname: "Mary", lname: "Jones"}
// 2: TestObject {id: "3", fname: "Larry", lname: "Murray"
setTimeout(() => {
temp.fname = 'Bartholomew';
console.log(this.testService.getData());
}, 5000);
// 0: TestObject {id: "1", fname: "Joe", lname: "Smith"}
// 1: TestObject {id: "2", fname: "Mary", lname: "Jones"}
// 2: TestObject {id: "3", fname: "Bartholomew", lname: "Murray"}
}
}
在组件中,通过调用testService.getData()方法在ngOnInit中初始化testComponentData属性,该方法返回this.serviceData.slice()
在这个例子中,我点击第3个按钮将fname设置为'Bartholomew'。正如您在嵌入式注释中看到的那样,testService数据发生了变化,即使我只是更改了组件对象(testComponentData),服务数据也在被更改(this.testService.getData())
超时就在那里,因为有时第一个console.log是滞后的,log会显示值已经改变了。
我不能为我的生活看到这是怎么回事。我知道这里有一些基本的东西,我假设我以某种方式访问同一个对象,但我不明白为什么。
任何帮助表示赞赏。谢谢!
由于对象的引用相同,对象将发生更改。现在需要克隆,如果你不想影响原始对象。尝试以下代码
声明克隆数组:
clonedTestComponentData: TestObject[];
克隆数组:
const this.clonedTestComponentData = Object.assign([], this.testComponentData);
克隆一个对象:
const temp = Object.assign({}, this.testComponentData.find(o => o.id === id));
这是因为对象数组上的Array.slice正在创建一个新数组,其值是对原始对象的引用。您不会看到类似字符串或数字数组的功能。您可以从this answer获得有关浅复制数组的更多信息。
空.slice()
调用是复制数组的已知快捷方式。类似于使用传播[...someArray]
运算符。但是,由于数组的内容是对象,因此它们通过引用返回到新数组中。
基本上,两个数组,即服务中的
serviceData
和组件中的temp
都共享相同的对象引用。
因此,更新temp
中项目的值也反映在serviceData
数组中。