正如标题所示,我有一个递归实例化的组件组。组件基于名为Item的树状数据模型,并通过递归调用模板并将模型的嵌套数组作为@Input()值传递,在嵌套列表中实例化。虽然这很好,但问题是操纵数据(存储在list.service.ts中)定义了此模板实例化的次数会导致某些错误。我有两个按钮连接到两个功能。一个删除特定项目并在项目树中向上移动剩余项目。这很好用。另一个按钮应该删除给定项目的项目数组中的所有项目,有效地删除其子项目。有趣的是,"删除和转移"函数只有在我的服务和组件使用主题和订阅时才能正常工作。虽然"删除孩子"如果我不使用订阅,函数似乎只能正常工作。相反,它似乎破坏了我点击的组件实例的组件实例"删除子项" (这不应该发生,因为我没有删除这个项目,只是它的项目数组),然后从根组件重建嵌套组件。
例如,如果我有以下嵌套项数组由DOM中的组件呈现:
然后我点击了第3项上的删除子项按钮,我希望为项目4调用onDestroy,保持项目1,2和3不变,但最终看起来像是这样:
我希望任何比我更了解Angular 2生命周期钩子的人是1)为什么订阅会阻止删除子项功能正常工作,2)为什么项目树得到每当我单击“删除子项”按钮时,从根节点重建,以及3)如何更改代码以解决此问题?
item.model.ts
export class Item{
constructor(public id: number, public details: string, public date: Date, public items?: Item[]){}
}
项-list.component.html
<div *ngFor="let item of items">
<ul>
<li> {{item.details}}
<br>
<button (click)="onDelete(item.id)">Delete</button>
<button (click)="onDeleteChildren(item.id)">
Delete Children</button>
<app-item-list [items]="item.items" *ngIf="item.items">
</app-item-list>
</li>
</ul>
</div>
项-list.component.ts
@Input() items: Item[] = [];
listSubscription: Subscription;
constructor(private list: ListService) {
this.items = this.list.getItems();
console.log('constructor called');
this.listSubscription = this.list.listUpdated.subscribe(
(items: Item[]) => {
this.items = items;
}
);
}
onDelete(index: number) {
this.list.deleteItemAndShiftChildren(index);
}
onDeleteChildren(index: number) {
this.list.deleteChildItems(index);
}
list.service.ts
deleteChildItems(index: number) {
this.recursiveChildDelete(this.items, index);
this.listUpdated.next(this.items.slice());
}
deleteItemAndShiftChildren(index: number) {
this.recursiveChildShift(this.items, this.items[0], index);
this.listUpdated.next(this.items.slice());
}
recursiveChildDelete(items: Item[], index: number) {
items.forEach( element => {
if (element.id === index) {
if(element.items){
element.items = [];
}
} else if (element.items) {
this.recursiveChildDelete(element.items, index);
}
});
}
recursiveChildShift(items: Item[], oldItem: Item, index: number) {
items.forEach( element => {
// if the id of the element to be deleted is found
if (element.id === index) {
//if the deleted element is the root node
if(oldItem==element){
if(element.items){
this.items = element.items;
return;
} else {
this.items = [];
return;
}
}
oldItem.items = element.items;
return;
} else if (element.items) {
oldItem = element;
this.recursiveChildShift(element.items, oldItem, index);
}
});
}
答案 0 :(得分:0)
事实证明解决这个问题有两个关键:
1)我使用的样本数据没有正确使用。我的items数组中的两个项目的id值相同,这给我一个特定操作的奇怪错误。所以我解决了这个问题。
2)我创建了一个根组件,该组件持有对我的服务中的数组的订阅,该数组将其值传递给递归生成列表的子组件。这样我只有一个地方,即根,从服务主体接收更新,并从该根组件构建数组。我最初这样做的方式,我的每个组件都是组件树的一部分,在我的服务中订阅了Subject,这是错误的。