Angular 2 *ngFor 在每次更改检查时重新创建组件
Angular 2 *ngFor recreates components on every change check
我有两个嵌套的 *ngFor
循环,一个遍历库,另一个遍历该库的所有项目,每个项目都有一个 angular 组件。
现在的问题是,在 angular 的每次更改检查中都会重新创建这些项目组件,我通过将记录器放入项目组件的 ngOnInit()
处理程序中注意到了这一点。每当我更改页面上的任何内容时都会调用此记录器,导致组件的状态重置并且所有更改都丢失,因此我无法修改组件的状态,这完全破坏了我的应用程序的功能。
我尝试使用 trackBy: trackByFn
来解决这个问题,但这也没有帮助。
容器:
<div *ngFor="let lib of libraries">
<div *ngIf="lib.components.length" class="groupContainer" [class.closed]="!libraryIsOpened(lib)">
<div class="title flex flex-row" (click)="toggleLibrary(lib)">
<p>{{ lib.name === '__none' ? 'No Library' : lib.name }} ({{ lib.components.length }})</p>
<div class="flex flex-grow"></div>
<i class="mdi mdi-chevron-up iconClose"></i>
<i class="mdi mdi-chevron-down iconOpen"></i>
</div>
<div class="content">
<app-component-list-item *ngFor="let c of components; trackBy: trackByFn"
class="flex"
[component]="c">
</app-component-list-item>
</div>
</div>
</div>
列表项:
import ...
@Component({
selector: 'app-component-list-item',
templateUrl: './component-list-item.component.html',
styleUrls: ['./component-list-item.component.scss']
})
export class ComponentListItemComponent implements OnInit {
@Input() component: PipelineComponent
constructor(private el: ElementRef, private nodeCreator: NodeCreationService) {
}
ngOnInit() {
console.log('init')
}
trackByFn(index, item) {
return this.component.componentID
}
}
如果不查看您的更多代码,很难确定。但我怀疑这是因为 libraries
正在改变(你在使用 Redux 吗?这需要顶级 libraries
列表来改变它任何元素或元素的 属性 已经改变),所以Angular change detections 发现它已经改变(并且不够聪明,无法知道里面的元素是相同的),因此为它的每个元素重新创建新的组件。如果是这种情况,那么您应该在父组件中存储库的可变副本,并就地更改它,这样 Angular 就不会认为当一个元素发生变化时整个事情都发生了变化。
我有两个嵌套的 *ngFor
循环,一个遍历库,另一个遍历该库的所有项目,每个项目都有一个 angular 组件。
现在的问题是,在 angular 的每次更改检查中都会重新创建这些项目组件,我通过将记录器放入项目组件的 ngOnInit()
处理程序中注意到了这一点。每当我更改页面上的任何内容时都会调用此记录器,导致组件的状态重置并且所有更改都丢失,因此我无法修改组件的状态,这完全破坏了我的应用程序的功能。
我尝试使用 trackBy: trackByFn
来解决这个问题,但这也没有帮助。
容器:
<div *ngFor="let lib of libraries">
<div *ngIf="lib.components.length" class="groupContainer" [class.closed]="!libraryIsOpened(lib)">
<div class="title flex flex-row" (click)="toggleLibrary(lib)">
<p>{{ lib.name === '__none' ? 'No Library' : lib.name }} ({{ lib.components.length }})</p>
<div class="flex flex-grow"></div>
<i class="mdi mdi-chevron-up iconClose"></i>
<i class="mdi mdi-chevron-down iconOpen"></i>
</div>
<div class="content">
<app-component-list-item *ngFor="let c of components; trackBy: trackByFn"
class="flex"
[component]="c">
</app-component-list-item>
</div>
</div>
</div>
列表项:
import ...
@Component({
selector: 'app-component-list-item',
templateUrl: './component-list-item.component.html',
styleUrls: ['./component-list-item.component.scss']
})
export class ComponentListItemComponent implements OnInit {
@Input() component: PipelineComponent
constructor(private el: ElementRef, private nodeCreator: NodeCreationService) {
}
ngOnInit() {
console.log('init')
}
trackByFn(index, item) {
return this.component.componentID
}
}
如果不查看您的更多代码,很难确定。但我怀疑这是因为 libraries
正在改变(你在使用 Redux 吗?这需要顶级 libraries
列表来改变它任何元素或元素的 属性 已经改变),所以Angular change detections 发现它已经改变(并且不够聪明,无法知道里面的元素是相同的),因此为它的每个元素重新创建新的组件。如果是这种情况,那么您应该在父组件中存储库的可变副本,并就地更改它,这样 Angular 就不会认为当一个元素发生变化时整个事情都发生了变化。