[英]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
都會重新初始化。 我可以確認,因為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項目的方法。 這是我所謂的發射輔助函數:
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");
}
}
你正在改變你的this.texts
屬性,它是*ngFor
結合這,反過來,你的父app-text
組件。
這意味着:
this.texts
*ngFor
為前值this.texts
得到(與所有一起刪除app-text
它們是子組件) 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.