在项目中很多地方,后端都返回的是组织表的列表数据,例如下面数据
[{
"createBy": "admin",
"createTime": "2023-05-09 05:54:01",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 100,
"parentId": 0,
"ancestors": "0",
"deptName": "若依科技",
"orderNum": 0,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null,
"children": []
}, {
"createBy": "admin",
"createTime": "2023-05-09 05:54:01",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 101,
"parentId": 100,
"ancestors": "0,100",
"deptName": "深圳总公司",
"orderNum": 1,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null,
"children": []
}]
但是我们使用一些前端ui组件需要传递指定格式的数据,才能展示树结构,页面样式如下
这种展示方式,同侧边栏展示方式如出一辙,那么就来学习一下若依的转换树结构吧
/**
* 构造树型结构数据
* @param {*} data 数据源
* @param {*} id id字段 默认 'id'
* @param {*} parentId 父节点字段 默认 'parentId'
* @param {*} children 孩子节点字段 默认 'children'
*/
export function handleTree(data, id, parentId, children) {
//增加灵活性 可配置children获取哪个字段
let config = {
// 例如id传入为'deptId' 则获取传入数据的'deptId'作为转换后数结构的id
id: id || 'id',
//同上,一般该参数不传递,传递也可支持,使该方法更加灵活
parentId: parentId || 'parentId',
childrenList: children || 'children'
};
//定义一个map key 使用parentId map用来获取该parentId下的所有子数据
var childrenListMap = {};
//这里就是传入data,只是key 为数据id map为该条数据
var nodeIds = {};
//这里用来装树结构,一般该数组只有一条数据,为没有parentId的数据
var tree = [];
//循环数据,收集到childrenListMap中,使所有数据有KEY: parentId value: 所有子数据
for (let d of data) {
//获取parentId 如果传递了parentId,则在data中获取你指定字段作为parentId
let parentId = d[config.parentId];
//如果没有parentId 说明是顶层数据
if (childrenListMap[parentId] == null) {
//例如 parentId=0 childrenListMap[0]为null 则初始化value为数组,用来装该parentId下的所有children节点
childrenListMap[parentId] = [];
}
//这里将所有的data都装到了nodeIds中
nodeIds[d[config.id]] = d;
//添加该parentid下的一条chilren节点数据
childrenListMap[parentId].push(d);
}
//填充一条顶层数据(没有parentId的数据)到tree中,配置正确tree只有一条数据
for (let d of data) {
//判断parentId为空,则说明该条数据为顶层数据,加入到tree中
let parentId = d[config.parentId];
if (nodeIds[parentId] == null) {
tree.push(d);
}
}
//此时便利tree中数据,并挨个将下面的chilren填充
for (let t of tree) {
adaptToChildrenList(t);
}
//挨个向下填充children
//第一次进来,说明该数据为顶层数据
function adaptToChildrenList(o) {
//获取收集好的,根据parentid可以获取到所有children 的map结构数据childrenListMap
//顶层数据的id就是子节点数据的parentId,从childrenListMap获取该parentId所有的子节点填充到顶层数据的chilren字段中
if (childrenListMap[o[config.id]] !== null) {
o[config.childrenList] = childrenListMap[o[config.id]];
}
//如果顶层数据的chilren节点有值,就是上面填充的chilren,说明还需要依次填充顶层节点下面chhilren的chilren,那么再挨个便利chilren再走一遍此方法,往下进行填充
if (o[config.childrenList]) {
for (let c of o[config.childrenList]) {
adaptToChildrenList(c);
}
}
}
//最后返回前端要的树节点
return tree;
}
转换之后的json格式如下
[{
"createBy": "admin",
"createTime": "2023-05-09 05:54:01",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 100,
"parentId": 0,
"ancestors": "0",
"deptName": "若依科技",
"orderNum": 0,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null,
"children": [{
"createBy": "admin",
"createTime": "2023-05-09 05:54:01",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 101,
"parentId": 100,
"ancestors": "0,100",
"deptName": "深圳总公司",
"orderNum": 1,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null,
"children": [{
"createBy": "admin",
"createTime": "2023-05-09 05:54:01",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 103,
"parentId": 101,
"ancestors": "0,100,101",
"deptName": "研发部门",
"orderNum": 1,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null
}, {
"createBy": "admin",
"createTime": "2023-05-09 05:54:01",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 104,
"parentId": 101,
"ancestors": "0,100,101",
"deptName": "市场部门",
"orderNum": 2,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null
}, {
"createBy": "admin",
"createTime": "2023-05-09 05:54:01",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 105,
"parentId": 101,
"ancestors": "0,100,101",
"deptName": "测试部门",
"orderNum": 3,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null
}, {
"createBy": "admin",
"createTime": "2023-05-09 05:54:02",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 106,
"parentId": 101,
"ancestors": "0,100,101",
"deptName": "财务部门",
"orderNum": 4,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null
}, {
"createBy": "admin",
"createTime": "2023-05-09 05:54:02",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 107,
"parentId": 101,
"ancestors": "0,100,101",
"deptName": "运维部门",
"orderNum": 5,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null
}]
}, {
"createBy": "admin",
"createTime": "2023-05-09 05:54:01",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 102,
"parentId": 100,
"ancestors": "0,100",
"deptName": "长沙分公司",
"orderNum": 2,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null,
"children": [{
"createBy": "admin",
"createTime": "2023-05-09 05:54:02",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 108,
"parentId": 102,
"ancestors": "0,100,102",
"deptName": "市场部门",
"orderNum": 1,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null
}, {
"createBy": "admin",
"createTime": "2023-05-09 05:54:02",
"updateBy": null,
"updateTime": null,
"remark": null,
"deptId": 109,
"parentId": 102,
"ancestors": "0,100,102",
"deptName": "财务部门",
"orderNum": 2,
"leader": "若依",
"phone": "15888888888",
"email": "ry@qq.com",
"status": "0",
"delFlag": "0",
"parentName": null
}]
}]
}]