2017-09-29 3 views
0

J'ai quelques problèmes avec text.component (sélecteur app-text) initialisant au milieu de la durée de vie de l'application (pas seulement quand je le crée).ngOnInit appelé au milieu de la vie du composant

Ceci est app.component.html:

<div class="container-fluid" *ngFor="let text of texts;let i=index"> 
    <app-text (textInfoEmitter)="dataFromChild($event)" [elementId]=i [ngStyle]="{'transform': getRotation(i), 'font-size.px':getFontSize(i)}" ></app-text> 
    </div> 

J'Emitting les données de app-text avec textInfoEmitter fonction et mise à jour du modèle app.component.ts avec dataFromChild(e). J'ai remarqué que chaque textInfoEmitter émet, app-text est réinitialisé. Je peux confirmer cela parce que les fonctions ngOnInit et constructor sont appelées.

Ce fichier est app.component.ts:

export class AppComponent implements OnInit { 
    texts: [TextModel]; 

    ngOnInit() { 
    this.texts = [ 
     { 
     rotation: 30, 
     fontSize: 16, 
     offset: { left: 120, top: 200 }, 
     scale: 1.4 
     } 
    ] 
    } 

    dataFromChild(e) { 
    this.texts[e.elementID] = { 
     rotation: e.rotation, 
     fontSize: e.fontSize, 
     offset:e.offset, 
     scale: 1 
    } 

    } 
    getRotation(i: number) { 
    return "rotate(" + this.texts[i].rotation + "deg)"; 
    } 
    getFontSize(i: number) { 
    return this.texts[i].fontSize; 
    } 
} 

Le text.component.ts est alambiquée et je n'ai pas trouvé un moyen de reproduire un projet complexe angulaire en ligne. Ceci est la fonction d'aide émettre I appel:

emitData(e){ 
    if ($(e).hasClass("h")){ 
     this.parentId = $(e).attr("id"); 
    }else{ 
     this.parentId = $(e).parent().attr("id"); 
    } 

    this.textInfoEmitter.emit(
     { 
     elementID: this.parentId, 
     rotation: this.delta.circleX, 
     fontSize: this.delta.fontSize, 
     offset: { 
      left: this.drag.x, 
      top: this.drag.y 
     } 
     } 
    ); 
    } 

delta et drag sont des modèles en text.component.ts.

Ma question est la suivante: dans quelles situations un composant est-il réinitialisé pendant sa durée de vie? Comment cela peut-il être évité?

Réplique d'un problème. Je fais essentiellement la même chose, en utilisant la directive ngFor et en mettant à jour le modèle avec EventEmitter. Cette fois, ngOnInit ne se déclenche pas lorsque le modèle est mis à jour.

app.component.ts

import { Component } from '@angular/core'; 
declare var $; 
@Component({ 
    selector: 'app-root', 
    template: ` 
    <div class="container-fluid" *ngFor="let text of texts; let i = index"> 
<app-text id="i" (dataEmitter)="setData($event)" [ngStyle]="{'transform': getRotation()}"></app-text> 
</div> 
    `, 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent { 
    texts = [ 
    {rotate:10} 
    ]; 

    ngOnInit(){ 
    } 
    getRotation(){ 
    return "rotate("+this.texts[0].rotate+"deg)"; 
    } 
    setData(e){ 
     this.texts[0].rotate = e; 
    } 
} 

text.component.ts

import { Component, OnInit, Output, EventEmitter } from '@angular/core'; 
declare var $; 
@Component({ 
    selector: 'app-text', 
    template:`<div tabindex="-1" (mousedown)="mousedown($event)" (focusout)="focusout($event)">Text</div>` , 
    styleUrls: ['./text.component.css'] 
}) 
export class TextComponent implements OnInit { 

@Output() dataEmitter = new EventEmitter(); 
    constructor() { } 

    ngOnInit() { 
    console.log("ng on Init"); 
    } 
    mousedown(e){ 
    $(e.target).focus(); 
    $(e.target).addClass("selected"); 
    this.dataEmitter.emit(50); 
    } 
    focusout(e){ 
    console.log("f out"); 
    $(e.target).removeClass("selected"); 
    } 
} 

Répondre

1

vous changez votre propriété this.texts qui est que *ngFor se lie à ce qui est, à son tour, un parent de votre app-text composant.

ce que cela signifie est:

  1. vous changer this.texts
  2. vos éléments DOM créés par *ngFor pour la valeur précédente de this.texts est alors retiré (en même temps que tous app-text composants qui sont des enfants)
  3. nouvelle itération par this.texts se produit avec les nouvelles instances de app-text pour chaque
+0

J'ai ajouté un autre code, qui est une réplique d'un problème. J'utilise ngFor et j'émets des données, juste avant. Mais dans ce cas, ngOnInit ne se déclenche pas lorsque le modèle est mis à jour. – sanjihan

0

Grâce à @dee zg, le problème a été résolu. Lorsque le modèle change, Angular réinitialise effectivement tout le contenu de la directive * ngFor. Sous le capot, il essaie de déterminer s'il doit détruire et créer des éléments dom.

Si vous modifiez tout l'objet du modèle, angular créera des éléments dom, mais si vous ne modifiez que les propriétés de l'objet modèle, ce ne sera pas le cas.

Par exemple:

this.texts[0] = {rotation:0, fontSize:23} provoquera le contenu de ngFor à détruire et recréés.

Mais si vous utilisez ceci:

this.texts[0].rotation = 0; 
this.texts[0].fontSize = 23; 

il ne sera pas.

+0

bien sûr, car cela ne change pas la référence à l'objet. –