背景说明
我们用nodejs重构若依的后台服务,发现有些数据需要返回树状结构,比如:
- 用户列表左侧的部门树
- 新增角色的菜单树等
那么,能否抽离出公共方法呢
封装函数
封装的好处:返回的id和label,支持传入不同的字段名
使用方法
部门树
deptTreeList
就是包含id、label、parentId的树状结构,但是这里多了一个parentId
字段,为了美观大家可以自己去除
// 从部门表取关键数据
const rows = await this.deptEntity.find({
select: ['deptId', 'parentId', 'deptName'],
});
// 构造树状结构
const deptTreeList = listToTree(rows, (m) => m.deptId, (m) => m.deptName);
菜单树
menuTreeList
菜单树
const rows = await this.menuEntity.find({
select: ['menuId', 'menuName', 'parentId'],
order: {
orderNum: 'ASC',
createTime: 'DESC'
}
})
const menuTreeList = listToTree(rows, (m) => m.menuId, (m) => m.menuName)
源码
interface treeNode {
id: number;
label: string;
parentId: number
}
/**
* 数组转树结构,返回以下树状结构
*/
export function listToTree(arr: any[], getId: any, getLabel: any): treeNode[] {
const kData = {}; // 以id做key的对象 暂时储存数据
const lData = []; // 最终的数据 arr
arr.forEach((m) => {
m = {
id: getId(m),
label: getLabel(m),
parentId: +m.parentId,
};
kData[m.id] = {
id: m.id,
label: m.label,
parentId: m.parentId,
};
if (m.parentId === 0) {
lData.push(kData[m.id]);
} else {
kData[m.parentId] = kData[m.parentId] || {};
kData[m.parentId].children = kData[m.parentId].children || [];
kData[m.parentId].children.push(kData[m.id]);
}
});
return lData;
}