2017-09-29 5 views
0

text.component(セレクタapp-text)で問題が発生しました(作成時だけでなく)アプリの使用期間の途中で初期化されました。ngOnInitがコンポーネントライフタイムの途中で呼び出されました

これは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> 

私はtextInfoEmitter機能をapp-textからデータを放出し、dataFromChild(e)app.component.tsでモデルを更新しています。

私が気づいたのは、textInfoEmitterが、app-textが再初期化されることに気づきました。私は、ngOnInitconstructor関数が呼び出されていることを確認できます。

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

text.component.tsが複雑であると私はオンライン複雑な角度プロジェクトを複製する方法を発見していない:

これはapp.component.tsファイルです。これは私が発するヘルパー関数を呼び出している:

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

deltadragtext.component.tsでモデルです。

私の質問は、コンポーネントが生涯にどのような状況で再初期化されるのですか?どのようにこれを防ぐことができますか?

問題のレプリカです。 ngFor指示句を使用してEventEmitterでモデルを更新することで、同じことをする必要があります。今回は、モデルの更新時にngOnInitが起動されません。

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

答えて

1

あなたは*ngForバインドが順番に、これはすることです、あなたのthis.texts財産、あなたの親を変更しますapp-textコンポーネント。

何それが意味することは次のとおりです。

  1. はあなたを介して
  2. 新たな反復(子であるすべてのapp-text成分と一緒に)
  3. this.textsの前回値を*ngForで作成したDOM要素this.textsを変更削除されますthis.textsは、それぞれについてapp-textの新しいインスタンスで発生します。
+0

問題のレプリカである別のコードを追加しました。私はngForを使用してデータを発信しています。しかし、この場合、モデルの更新時にngOnInitは起動しません。もちろんそれはオブジェクトへの参照を変更しないので、 – sanjihan

0

@dee zgのおかげで問題は解決しました。

モデルが変更されると、Angularは実際に* ngForディレクティブの内容全体を再初期化します。そのフードの下で、DOM要素を破壊して作成する必要があるかどうかを判断しようとします。

モデルオブジェクト全体を変更すると、角度が新しくdom要素を作成しますが、モデルオブジェクトのプロパティだけを変更してもそれは作成されません。例えば

this.texts[0] = {rotation:0, fontSize:23}がngForの内容が破壊され、再作成されるようになります。あなたがこれを使用する場合

しかし:

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

それはしません。

+0

です。 –

関連する問題