我遇到了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
都会被重新初始化。我可以确认,因为ngOnInit
和constructor
函数被调用。
这是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
}
}
);
}
delta
和drag
是text.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");
}
}
答案 0 :(得分:1)
您正在更改this.texts
属性*ngFor
属性,而app-text
属性又是this.texts
组件的父级。
这意味着:
*ngFor
this.texts
为先前的app-text
值创建的DOM元素将被删除(与所有this.texts
组件一起被删除)app-text
的新迭代发生在每个 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;
它不会。