簡體   English   中英

ngOnInit在組件生命周期的中間被調用

[英]ngOnInit called in the middle of component lifetime

我在應用程序生命周期的中間(而不是僅在創建它的時候)初始化text.component (選擇器app-text )時遇到一些問題。

這是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函數被調用了。

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

text.component.ts令人費解,我還沒有找到在線復制復雜的Angular項目的方法。 這是我所謂的發射輔助函數:

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

你正在改變你的this.texts屬性,它是*ngFor結合這,反過來,你的父app-text組件。

這意味着:

  1. 您更改this.texts
  2. 通過創建你的DOM元素*ngFor為前值this.texts得到(與所有一起刪除app-text它們是子組件)
  3. 通過this.texts新的迭代會為每個app-text添加新的實例

感謝@dee zg,問題得以解決。

當模型改變時,Angular確實會重新初始化* ngFor指令的全部內容。 在引擎蓋下,它試圖確定是否需要銷毀並創建dom元素。

如果修改整個模型對象,則angular將創建新的dom元素,但如果僅修改模型對象的屬性,則不會。

例如:

this.texts[0] = {rotation:0, fontSize:23}將導致ngFor的內容被破壞並重新創建。

但是,如果使用此命令:

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

它不會。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM