2017-09-29 3 views
0

Ich habe einige Probleme mit text.component (Selektor app-text) Initialisierung in der Mitte der App-Lebenszeit (nicht nur, wenn ich es erstelle).ngOnInit in der Mitte der Lebensdauer der Komponente aufgerufen

Dies ist 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> 

ich die Daten aus app-text mit textInfoEmitter Funktion und zur Aktualisierung des Modells in app.component.ts mit dataFromChild(e) emittieren.

Ich bemerkte, dass jedes Mal textInfoEmitter ausstrahlt, app-text wird reinitialisiert. Ich kann das bestätigen, weil ngOnInit und constructor Funktionen aufgerufen werden.

Dies ist app.component.ts Datei:

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

Die text.component.ts ist verworren und ich habe einen Weg kein komplexes Angular Projekt online zu replizieren gefunden. Dies ist die auszusenden Helferfunktion Ich nenne:

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 und drag sind Modelle in text.component.ts.

Meine Frage ist, in welchen Situationen wird eine Komponente während der Lebensdauer reinitialisiert? Wie kann dies verhindert werden?

Replik eines Problems. Ich tue das im Wesentlichen genauso, benutze ngFor Direktive und aktualisiere das Modell mit EventEmitter. Dieses Mal wird ngOnInit nicht ausgelöst, wenn das Modell aktualisiert wird.

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

Antwort

1

Sie Ihre this.texts Eigenschaft zu ändern, das ist, dass *ngFor bindet, was wiederum heißt, ein Elternteil Ihrer app-text Komponente.

was das bedeutet ist:

  1. Sie this.texts von *ngFor für vorherigen Wert von this.texts wird (zusammen mit allen app-text Komponenten, die Kinder sind) entfernt erstellt
  2. Ihre DOM-Elemente ändern durch
  3. neue Iteration this.texts passiert mit neuen Instanzen von app-text für jeden
+0

Ich habe einen anderen Code hinzugefügt, der eine Replik eines Problems ist. Ich benutze ngFor und emittiere Daten, nur ein s vorher. In diesem Fall wird ngOnInit jedoch nicht ausgelöst, wenn das Modell aktualisiert wird. – sanjihan

0

Dank @dee zg wurde das Problem gelöst.

Wenn sich das Modell ändert, reinitialisiert Angular tatsächlich den gesamten Inhalt der * ngFor-Anweisung. Unter der Haube versucht es festzustellen, ob es dom Elemente zerstören und erstellen muss.

Wenn Sie das gesamte Modellobjekt ändern, erstellt angular neue dom-Elemente. Wenn Sie jedoch nur die Eigenschaften des Modellobjekts ändern, wird dies nicht der Fall sein.

Zum Beispiel:

this.texts[0] = {rotation:0, fontSize:23} wird der Inhalt von ngFor verursachen zerstört und neu erstellt werden.

Aber wenn Sie verwenden:

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

wird es nicht.

+0

natürlich, weil das den Verweis auf das Objekt nicht ändert. –