[英]Angular2 Child component destroyed unexpectedly in ngFor
所以我有一个带有@Output
事件的from的Component,它在提交时触发,如下所示:
@Component({
selector: 'some-component',
templateUrl: './SomeComponent.html'
})
export class SomeComponent{
@Input() data: any;
@Output() onSubmit: EventEmitter<void> = new EventEmitter<void>();
constructor(private someService: SomeService) {}
submitForm(): void{
this.someService.updateBackend(this.data, ()=>{
this.onSubmit.emit();
});
}
}
我正在使用ngFor
来创建此Component的多个元素:
<template let-data ngFor [ngForOf]="dataCollection">
<some-component [data]="data" (onSubmit)="doSomthing()"></some-component>
</template>
最后一个缺失的部分是提交时使用的服务:
@Injectable()
export class SomeService{
constructor() {}
updateBackend(data: any, callback: () => void): void{
/*
* updating the backend
*/.then((result) => {
const { errors, data } = result;
if (data) {
callback();
}
})
}
}
在submitForm()
函数的开头, this.onSubmit.observers
是一个包含一个观察者的数组,就像它应该的那样。
一旦它到达调用this.onSubmit.emit()
的回调方法, this.onSubmit.observers
就是一个包含ZERO观察者的数组。
SomeService.updateBackend
的后端它完全正常, observers
仍然是一个包含一个观察者的数组! ngFor
并且只显示一个<some-element>
它也可以正常工作,将一个观察者this.onSubmit.observers
在回调范围内的this.onSubmit.observers
中! 知道我做错了什么吗?
提前致谢!
感谢@ StevenLuke的有关登录评论ngOnDestroy
的SomeComponent
我发现,它是在EMIT之前销毁。
实际上,当SomeService.updateBackend
完成时,它正在做的第一件事是销毁该组件的所有实例并重新创建它们!
这就是观察者改变的原因! 为什么会这样?
如果在* ngFor中提供trackBy函数来标识dataCollection中的项,则不会销毁和初始化。 你的模板是:
<some-component *ngFor="let data of dataCollection;trackBy:trackByFunction"
[data]="data" (onSubmit)="doSomthing()"></some-component>
trackByFunction看起来像:
trackByFunction(index, item) {
return item ? item.id : undefined;
}
因此,即使dataCollection中的项是新对象,如果其id与前一个集合中的id匹配,* ngFor将更新[data]但不会销毁并初始化该组件。
感谢@GünterZöchbauer评论我发现情况是ngFor
绑定的数据被更新后端的新实例替换,因此,它重新渲染了它的子组件导致它们重新初始化(destory + init),使Component的实例被覆盖。
为了解决这个问题,我必须将dataCollection
放在一个单独的服务中,为父组件ngOnInit
获取它,保存它不会导致重新ngFor
,并且只有在子组件执行结束后再次获取它的数据
希望它对某人有帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.