假设我有一个看起来像这样的员工类:
export class Employee {
jobTitle: string;
firstName: string;
lastName: string;
boss: Employee;
workers: Employee[];
constructor(jobTitle: string, firstName: string, lastName: string){
this.jobTitle = jobTitle;
this.firstName = firstName;
this.lastName = lastName;
}
public addWorker(worker: Employee){
this.wokers.push(worker);
worker.boss = this;
}
}
假设我们的初始Employee
s 看起来像这样:
function getInitialStaff(): Employee {
let headWaiter: Employee = new Employee( "Head Waiter", "Sarah", "Hilton" );
headWaiter.addWorker(new Employee("Bus Boy", "Joe", "BeefEater"));
headWaiter.addWorker(new Employee("Waiter", "Randy", "Rainman"));
let headCheif: Employee = new Employee( "Head Cheif", "Phil", "Yorstomux" );
headWaiter.addWorker(new Employee("Dishwasher", "Andy", "Shark"));
let owner: Employee = new Employee( "Owner", "Boris", "Laughington" );
owner.addWorker(headWaiter);
owner.addWorker(headCheif);
return owner;
}
我们还可以假设有时员工会被雇用或解雇。类似这样的东西:
window.setTimeout(()=>{
let someEmployee: Employee = /* Some existing employee */
someEmployee.addWorker("someTitle", "someName", "someLastName");
}, someAmountOfTime);
我想在PrimeNg 树中显示员工。
树小部件要求要显示的数据符合 treeNode 接口,如下所示:
export interface TreeNode {
label?: string;
data?: any;
icon?: any;
expandedIcon?: any;
collapsedIcon?: any;
children?: TreeNode[];
leaf?: boolean;
}
主要问题:在不更改我的 Employee 类的情况下,将数据转换为 TreeNode 的最佳方法是什么?
我正在考虑的事情:
- 当我添加一个新员工时,我想保持我的树状态(什么是打开的,什么是选中的,等等)
- 我需要能够轻松检索当前选择的员工。
- 我试图避免维护两个重复的模型。
- 我想以一种合理但可扩展的方式利用 Angular2 的变更检测
这是我的 EmployeeTree 组件目前的样子:
@Component({
selector: 'employee-tree',
template: `
<div>
<p-tree>
/* Open Question, I need to transform owner and then tie the resulting TreeNode to the tree */
</p-tree>
</div>
`
directives: [ Tree ]
})
export class EmployeeTree {
@Input()
private owner: Employee;
}
选项 1 - 创建一个将 Employee 转换为 TreeNode 的管道
我想这会让我的模板看起来像这样:
<p-tree [value]="owner | convertToTreeNode"></p-tree>
我将创建一个执行以下操作的管道:
@Pipe({name: 'convertToTreeNode'})
export class ToTreeNode implements PipeTransform {
transform(employee: Employee): TreeNode {
let treeNode: TreeNode = {
label: employee.firstName + " " + employee.lastName,
data: employee,
children: []
};
employee.workers.forEach(worker => {
treeNode.children.push(this.transform(worker));
})
return treeNode;
}
}
优点缺点:
- 这利用了角度的变化检测
- 如果这是一个纯管道,它可能会错过更改
- 如果这是不纯的管道,它可能太重了
- 使组件非常干净并将责任委托给管道
- 不确定添加新项目时这是否会保留我的 gui 状态(选择什么以及打开/关闭什么)
选项 2 - 在组件内部为树维护一个单独的结构
@Component({
selector: 'employee-tree',
template: `
<div>
<p-tree [data]="employeeTree">
</p-tree>
</div>
`
directives: [ Tree ]
})
export class EmployeeTree {
@Input()
private owner: Employee;
private employeeTree: TreeNode;
// TODO - Somehow watch the owner for changes (how?) and then repopulate the employeeTree
}
我认为我可以让 Employee 发出一个事件,该事件在它发生变化时会溢出。这可以让我有所收获。
一般来说,使用Angular2做这样的事情的最好方法是什么。
总而言之,我想使用一个小部件,它期望数据的格式与我存储它的格式略有不同。将我的数据按摩到小部件中的标准 angular2 方法是什么?有特殊的 angular2 酱汁可以帮助我吗?我应该维护两个独立的模型吗?我的树中可能有 100 或 1000 件物品,所以我有点担心性能。