6

所以我有一个 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();
        });
    }
}

我正在使用一个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就是一个包含零观察者的数组。

我正在经历两种非常奇怪的行为:

  • 如果我删除了更新后端的实际调用,SomeService.updateBackend它工作得很好,而且observers仍然是一个包含一个观察者的数组!
  • 如果我保持对后端的实际调用但不使用ngFor和只显示一个<some-element>,它也可以正常工作,将一个观察者保持this.onSubmit.observers在回调范围内!

知道我在做什么错吗?

提前致谢!

更新:

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

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

这就是让观察者发生变化的原因!为什么会这样?

4

2 回答 2

10

如果您在 *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] 但不会销毁并初始化组件。

于 2017-02-14T19:45:56.220 回答
2

感谢@GünterZöchbauer的评论,我发现ngFor当我更新后端时,绑定到的数据被一个新实例替换,因此,它重新渲染了它的子组件,导致它们重新初始化(destory + init),这使得要覆盖的组件的实例。

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

希望它对某人有帮助!

于 2016-09-14T16:35:41.353 回答