Je travaille sur une application angular2 qui profite de plusieurs services pour partager des dates dans toute l'application.
Dans une partie de mon application, j'ai une fonction d'édition qui permet à l'utilisateur de modifier les données dans un tableau .
Dans ce cas, lorsque l'utilisateur modifie une propriété dans le composant, les données correspondantes dans le service sont également modifiées sans le définir directement.
Je suis depuis environ 6 mois à l'apprentissage angulaire, mais je sais que définir un tableau égal à un autre est en fait pointé vers le même objet. Donc, dans ce cas, j'ai une méthode dans le service qui renvoie le tableau sous forme de slice (), ce qui, je crois, est censé créer un nouveau tableau pour éviter que l'utilisateur ne puisse modifier directement les données du service.
L'application complète sur laquelle je travaille est assez complexe, mais j'ai pu créer une application angulaire simple pour montrer ce qui se passe.
XXX
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"} } }
@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(); } }
test.component.ts:
export class TestObject { constructor(public id: string, public fname: string, public lname: string) {}
Dans le composant, la propriété testComponentData est initialisée dans ngOnInit en appelant la méthode testService.getData (), qui renvoie this.serviceData. slice ()
Dans cet exemple, je clique sur le 3ème bouton pour définir le fname sur 'Bartholomew'. Comme vous le voyez dans les commentaires intégrés, les données testService changent, même si je ne modifie que l'objet composant (testComponentData), les données du service sont également modifiées (this.testService.getData ())
Timeout est juste là parce que parfois le premier console.log est lent et le journal montrera que la valeur a déjà changé.
Je ne peux pas pour la vie de moi voir comment cela se passe. Je sais qu'il y a quelque chose de fondamental ici, et je suppose que j'accède au même objet d'une manière ou d'une autre, mais je ne comprends pas pourquoi.
Toute aide est appréciée. Merci!
3 Réponses :
En effet, Array.slice < / a> sur un tableau d'objets crée un nouveau tableau dont les valeurs sont des références aux objets d'origine. Vous ne verrez pas cette fonctionnalité avec quelque chose comme une chaîne ou un tableau de nombres. Pour plus d’informations, consultez cette réponse sur les tableaux de copie superficiels.
Ah, merci OneLunch Man! Ça a du sens maintenant! J'aimerais pouvoir cocher plus d'une réponse.
L'appel vide .slice ()
est un raccourci connu pour répliquer un tableau. Similaire à l'utilisation de l'opérateur spread [... someArray]
. Cependant, comme le contenu du tableau est un objet, il est renvoyé par référence dans le nouveau tableau.
Fondamentalement, les deux tableaux, c'est-à-dire
serviceData
en service ettemp
en composants partagent les mêmes références d'objet.
Par conséquent, la mise à jour d'une valeur d'un élément dans temp
se reflète également dans le tableau serviceData
.
Merci Ashish! Toutes ces trois réponses m'ont aidé à comprendre ce qui se passait. Je vous en suis reconnaissant!
L'objet changera à cause de la même référence de l'objet. maintenant besoin de cloner si vous ne voulez pas l'effet de l'objet d'origine. Essayez de suivre le code
Déclarez le tableau de clonage:
const temp = Object.assign({}, this.testComponentData.find(o => o.id === id));
Cloner un tableau:
const this.clonedTestComponentData = Object.assign([], this.testComponentData);
Cloner un objet:
clonedTestComponentData: TestObject[];
Merci Shohel! J'apprécie que vous preniez le temps de donner des exemples de code sur la façon de cloner les objets et les tableaux.