javascript - Angular2 子组件在 ngFor 中意外销毁

标签 javascript angular components this ngfor

所以我有一个来自 @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创建此组件的多个元素:

<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 关于记录 ngOnDestroy 的评论的 SomeComponent我发现它在发出之前就被销毁了。

实际上,它在 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] 但不会销毁和初始化组件。

关于javascript - Angular2 子组件在 ngFor 中意外销毁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39471404/

相关文章:

javascript - 打印具有不同 div 大小的网页

javascript - 如何使用 three.js 在运行时绘制线段

javascript - 操作多个子组件的状态

asp.net - 网站的 HTML 色轮控件

javascript - 在 Google 标签管理器和 Google Analytics 中捕获 Hotjar 用户 ID

javascript - Animated.Component/createAnimatedComponent(Component) 与 Component 有何不同?

Angular 7 组件测试 - 如何验证输入元素值

angular - Angular Material 表中屏幕尺寸减小时如何支持相同的列尺寸

angular - 通用类型 'Observer<V, E>' 需要 2 个类型参数。 @firebase/app-types/private.d.ts

java - 使用 AWT 设置 java 元素的大小