1
votes

Pourquoi la modification de la valeur d'une propriété de composant change-t-elle automatiquement la propriété de service correspondante?

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.

test.component.html:

XXX

test.model.ts:

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"}

  }

}

test.service.ts:

@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!


0 commentaires

3 Réponses :



0
votes

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 et temp 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 .


1 commentaires

Merci Ashish! Toutes ces trois réponses m'ont aidé à comprendre ce qui se passait. Je vous en suis reconnaissant!



0
votes

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[];


1 commentaires

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.