AngFor2子组件在ngFor中意外销毁

Kes*_*vid 5 javascript components this ngfor angular

所以我有一个来自from的组件,该@Output事件在提交时触发,如下所示:

@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();
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用ngFor创建该Component的多个元素:

<template let-data ngFor [ngForOf]="dataCollection">
    <some-component  [data]="data" (onSubmit)="doSomthing()"></some-component>
</template>
Run Code Online (Sandbox Code Playgroud)

最后缺少的部分是用于提交的服务:

@Injectable()
export class SomeService{

    constructor() {}

    updateBackend(data: any, callback: () => void): void{
        /*
         * updating the backend
         */.then((result) => {
            const { errors, data } = result;

            if (data) {
                callback();
            }
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

submitForm()函数的开头,this.onSubmit.observers是一个包含一个观察者的数组,就像它应该那样。

一旦到达回调方法(在this.onSubmit.emit()处调用),则它this.onSubmit.observers是一个包含零观察者的数组。

我遇到两种非常奇怪的行为:

  • 如果我删除实际的调用以更新后端,SomeService.updateBackend则可以正常工作,而observers仍然是一个包含一个观察者的数组!
  • 如果我不对后端BUT进行实际调用而不使用它ngFor并仅显示一个,<some-element>那么它也可以正常工作,将一名观察者留this.onSubmit.observers在回调范围内!

知道我在做什么错吗?

提前致谢!

更新:

感谢@StevenLuke关于记录的评论ngOnDestroySomeComponent我发现它在发出之前已被销毁。

实际上,SomeService.updateBackend完成时要做的第一件事就是销毁该组件的所有实例并重新创建它们!

这就是使观察者改变的原因!为什么会这样?

小智 6

如果在* ngFor中提供trackBy函数以标识dataCollection中的项目,则该函数不会销毁和初始化。您的模板为:

<some-component *ngFor="let data of dataCollection;trackBy:trackByFunction"
  [data]="data" (onSubmit)="doSomthing()"></some-component>
Run Code Online (Sandbox Code Playgroud)

而trackByFunction看起来像:

trackByFunction(index, item) {
    return item ? item.id : undefined;
}
Run Code Online (Sandbox Code Playgroud)

因此,即使dataCollection中的项目是一个新对象,如果它的ID与上一个集合中的ID相匹配,* ngFor也会更新[data],但不会破坏和初始化该组件。


Kes*_*vid 2

感谢 @G\xc3\xbcnterZ\xc3\xb6chbauer 评论,我发现这种情况是,ngFor当我更新后端时,绑定到的数据被新实例替换,因此,它重新渲染了它的子组件,导致重新初始化(破坏+ init),这使得组件的实例被覆盖。

\n\n

为了解决这个问题,我必须将 放在dataCollection一个单独的服务中,为父组件获取它ngOnInit,避免它导致 的重新渲染ngFor,并仅在子组件执行结束后再次获取其数据

\n\n

希望它对某人有帮助!

\n