繁体   English   中英

Angular2子组件在ngFor中意外销毁

[英]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的有关登录评论ngOnDestroySomeComponent我发现,它是在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM