简体   繁体   English

ngOnInit在组件生命周期的中间被调用

[英]ngOnInit called in the middle of component lifetime

I having some issues with text.component (selector app-text ) initialising in the middle of the app life time (not just when I create it). 我在应用程序生命周期的中间(而不是仅在创建它的时候)初始化text.component (选择器app-text )时遇到一些问题。

This is app.component.html: 这是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>

I am emitting the data from app-text with textInfoEmitter function and updating the model in app.component.ts with dataFromChild(e) . 我使用textInfoEmitter函数从app-text发出数据,并使用dataFromChild(e)更新app.component.ts的模型。

I noticed that everytime textInfoEmitter emits, app-text gets reinitialised. 我注意到,每次textInfoEmitter发出时, app-text都会重新初始化。 I can confirm that because, ngOnInit and constructor functions get called. 我可以确认,因为ngOnInitconstructor函数被调用了。

This is app.component.ts file: 这是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;
  }
}

The text.component.ts is convoluted and I haven't found a way to replicate a complex Angular project online. text.component.ts令人费解,我还没有找到在线复制复杂的Angular项目的方法。 This is the emit helper function I call: 这是我所谓的发射辅助函数:

  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 and drag are models in text.component.ts . deltadragtext.component.ts中的模型。

My question is, in what situations does a component get reinitialised during lifetime? 我的问题是,在生命周期中哪种情况下会重新初始化组件? How can this be prevented? 如何预防?

Replica of a problem. 问题的副本。 I am essentialy doing the same, using ngFor directive and updating the model with EventEmitter. 我本质上是这样做的,使用ngFor指令并使用EventEmitter更新模型。 This time, ngOnInit does not get fired when the model updates. 这次,更新模型时不会触发ngOnInit。

app.component.ts 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 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");
  }
}

you are changing your this.texts property which is that *ngFor binds to which is, in turn, a parent of your app-text component. 你正在改变你的this.texts属性,它是*ngFor结合这,反过来,你的父app-text组件。

what that means is: 这意味着:

  1. you change this.texts 您更改this.texts
  2. your DOM elements created by *ngFor for previous value of this.texts gets removed (together with all app-text components which are children) 通过创建你的DOM元素*ngFor为前值this.texts得到(与所有一起删除app-text它们是子组件)
  3. new iteration through this.texts happens with new instances of app-text for each 通过this.texts新的迭代会为每个app-text添加新的实例

Thanks to @dee zg the problem was solved. 感谢@dee zg,问题得以解决。

When model changes, Angular does indeed reinitialise the whole contents of *ngFor directive. 当模型改变时,Angular确实会重新初始化* ngFor指令的全部内容。 Under the hood, it tries to determine if it needs to destroy and create dom elements. 在引擎盖下,它试图确定是否需要销毁并创建dom元素。

If you modify the whole model object, angular will create fresh dom elements, but if you modify just properties of the model object, it will not. 如果修改整个模型对象,则angular将创建新的dom元素,但如果仅修改模型对象的属性,则不会。

For example: 例如:

this.texts[0] = {rotation:0, fontSize:23} will cause the contents of ngFor to be destroyed and recreated. this.texts[0] = {rotation:0, fontSize:23}将导致ngFor的内容被破坏并重新创建。

But if you use this: 但是,如果使用此命令:

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

it will not. 它不会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ngOnInit 未在动态组件上调用 - ngOnInit is not called on dynamic component Angular 4组件@Input ngOnInit未调用 - Angular 4 Component @Input ngOnInit not called Angular 4 组件 ngOnInit 未在每个路由请求上调用 - Angular 4 Component ngOnInit not called on each route request 在ngOninit期间是否调用组件方法的角度测试? - Angular testing if component method is called during ngOninit? 如果页面是从另一个组件刷新和导航的,则不会在组件上调用 ngOnInit() - ngOnInit() not called on component if page was refreshed and navigated from another component 从另一个组件调用时ngOnInit()不会刷新该组件 - ngOnInit() when called from another component does not refresh the component angular5 - 在父ngOnInit完成之前调用的子组件 - angular5 - child component called before parent ngOnInit finish Angular 7 SSR,多次调用 App 组件 ngOnInit() - Angular 7 SSR, App component ngOnInit() called multiple times 当相同组件加载不同数据时,不会调用ngOnInit - ngOnInit not called when same component is loaded with different data Angular5 - 每次在页面上使用组件时都会调用 ngOnInit - Angular5 - ngOnInit called every time a component is used on the page
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM