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

时间:2017-09-29 08:50:28

标签: angular ngoninit

我遇到了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>

我使用app-text函数从textInfoEmitter发出数据,并使用app.component.ts更新dataFromChild(e)中的模型。

我注意到每次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项目。这是我调用的emit辅助函数:

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

2 个答案:

答案 0 :(得分:1)

您正在更改this.texts属性*ngFor属性,而app-text属性又是this.texts组件的父级。

这意味着:

  1. 您更改了*ngFor
  2. this.texts为先前的app-text值创建的DOM元素将被删除(与所有this.texts组件一起被删除)
  3. app-text的新迭代发生在每个
  4. 的新 var fs = require('fs'); var tar = require('tar'); var zlib = require('zlib'); var path = require('path'); var mkdirp = require('mkdirp'); var archiver = require('archiver'); var log = console.log; //https://stackoverflow.com/questions/21989460/node-js-specify-files-to-unzip-with-zlib-tar uid=Date.now().toString().substr(Date.now().toString().length - 4); const tempDir = require('temp-dir'); var destdir = tempDir + '\\lay'+uid+'.tmp'; mkdirp(destdir, function(err) { if (err) throw err; }); function unzip() { var srcdir = 'E:/d data/electron/Applications/FirstApp/js/red.le2'; //var destdir = 'E:/d data/electron/Applications/FirstApp/js/temp'; fs.createReadStream(srcdir) .on('error', log) .pipe(zlib.Unzip()) .pipe(new tar.Parse()) .on('entry', function(entry) { // if (/\.js$/.test(entry.path))// only extract JS files, for instance { var isDir = 'Directory' === entry.type; var fullpath = path.join(destdir, entry.path); var directory = isDir ? fullpath : path.dirname(fullpath); console.log (fullpath) mkdirp(directory, function(err) { if (err) throw err; if (! isDir) { entry.pipe(fs.createWriteStream(fullpath)); ; } }); } }); } function zip() { destdir='C:/Users/Raina/AppData/Local/Temp/lay0054.tmp'; var output = fs.createWriteStream('C:/Users/Raina/AppData/Local/Temp/xx.le2'); var archive = archiver('tar', { zlib: { level: 9 } }); output.on('close', function() { console.log(archive.pointer() + ' total bytes'); console.log('archiver has been finalized and the output file descriptor has closed.'); }); archive.on('warning', function(err) { if (err.code === 'ENOENT') { // log warning } else { // throw error throw err; } }); archive.on('error', function(err) { throw err; }); archive.pipe(output); archive.directory(destdir+'/layout', 'layout'); archive.file(destdir+'/layout_new.xml', { name: 'layout_new.xml' }); archive.finalize(); } 实例上

答案 1 :(得分:0)

感谢@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;

它不会。