[英]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. 我可以确认,因为ngOnInit
和constructor
函数被调用了。
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
. delta
和drag
是text.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: 这意味着:
this.texts
您更改this.texts
*ngFor
for previous value of this.texts
gets removed (together with all app-text
components which are children) 通过创建你的DOM元素*ngFor
为前值this.texts
得到(与所有一起删除app-text
它们是子组件) 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.