需求描述:
ant design vue tree组件样子如下:
要求后端返回数据格式如下:
那么后端如何组装这些树形结构的数据呢,在此引入我工作中用的例子,某项目下包含模块数据,模块在数据库中是以单个节点数据存在
页面效果:
数据库中模块数据:
拿第一个节点举例,组装好的数据应该是这样:
就是一个节点下,有children节点,然后children节点中海油children节点。
{ "children":[ { "children":[ { "children":[ { "children":[ ], "created_time":"2021-04-12 19:43:34", "ellipsisSeen":false, "id":12, "isLeaf":true, "key":12, "modified_time":"2021-05-21 10:30:31", "parent_module_id":9, "popoverVisible":false, "scopedSlots":{ "icon":"folder", "title":"custom" }, "status":"0", "title":"u6d4bu8bd5123", "tooltipVisible":false, "value":"12" } ], "created_time":"2021-03-22 21:06:25", "ellipsisSeen":false, "id":9, "isLeaf":false, "key":9, "modified_time":"2021-03-22 21:06:25", "parent_module_id":5, "popoverVisible":false, "scopedSlots":{ "icon":"folder-open", "title":"custom" }, "status":"0", "title":"u6ce8u518cu5b50u8282u70b9", "tooltipVisible":false, "value":"9" } ], "created_time":"2021-03-22 17:16:41", "ellipsisSeen":false, "id":5, "isLeaf":false, "key":5, "modified_time":"2021-03-22 17:17:21", "parent_module_id":1, "popoverVisible":false, "scopedSlots":{ "icon":"folder-open", "title":"custom" }, "status":"0", "title":"u6ce8u518c", "tooltipVisible":false, "value":"5" }, { "children":[ ], "created_time":"2021-03-22 17:18:27", "ellipsisSeen":false, "id":8, "isLeaf":true, "key":8, "modified_time":"2021-05-20 18:34:57", "parent_module_id":1, "popoverVisible":false, "scopedSlots":{ "icon":"folder", "title":"custom" }, "status":"0", "title":"u8d2du7269u8f66", "tooltipVisible":false, "value":"8" } ], "created_time":"2021-03-14 14:34:23", "ellipsisSeen":false, "id":1, "isLeaf":false, "key":1, "modified_time":"2021-05-21 10:40:25", "parent_module_id":0, "popoverVisible":false, "scopedSlots":{ "icon":"folder-open", "title":"custom" }, "status":"0", "title":" u6ce8u518cu4e0eu767bu5f55", "tooltipVisible":false, "value":"1" }
由于表中的节点信息都是一维的,父子关系是通过节点信息的parent_id字段关联,那么怎么组合成一个属性结构json数据呢。
这个开始看着还挺简单,可以越想越容易迷糊,为了搞清处理过程,我还在纸上画了下处理流程:
简单说下我的思路,如图上:
step1: 先遍历所有节点数据,把所有子节点都挂到父节点上
即:虽然不知道一个节点有多少个子节点,但是可以让所有的孩子都找到对应的父亲
按照数据表中的父子关系,可以把id从1到12的节点都找到对应的父亲
拿id为1、2节点数据举例,注意,此时1节点的所有层级的节点关系已经生成,即1的孩子是5和8,5的孩子是9,9的孩子是2,
2的孩子是6、7,6的孩子是10,10的孩子是11,即:
step2:遍历所有节点,如果其孩子节点在第一层节点中,则删除第一层节点
如下图:
过程:
1节点的孩子有5和8,则删除一层节点的5和8,
2节点的孩子有6和7,则删除一层节点的6和7
3和4节点没有孩子,不动
5的孩子是9,则删除一层节点的9
9的孩子是12,则删除一层节点的12,
依此类推,最后剩下的
数据结构即是:
第一层数据只剩4个节点:[1, 2, 3, 4],也就是最顶层只有4个模块,其他模块都是某个模块的孩子存在
1的孩子是[5, 8]
----5的孩子是9
--------9的孩子是12
2的孩子是[6, 7]
----6的孩子是10
--------10的孩子是11
生成的数据就是前面的json串了。
后端python代码
# 遍历第一遍,保证所有子节点都找到父节点 for k, v in res_dict.items(): print("k: {}".format(k)) print("v: {}".format(v)) parent_module_id = v.get("parent_module_id") # 如果数据有parent_module_id,则把该数据添加到res_dict_last字典中key为parent_module_id的value中的children中,然后从res_dict_last字典中删除该数据 if parent_module_id: if res_dict.get(parent_module_id, ""): res_dict.get(parent_module_id).get("children").append(v) print("res_dict first for: {}".format(res_dict)) # 遍历第二遍,处理元数据把scopedSlots加上 for one_k, one_v in res_dict.items(): if one_v.get("children"): one_v['scopedSlots'] = dict(title="custom", icon="folder-open") one_v['isLeaf'] = False else: one_v['scopedSlots'] = dict(title="custom", icon="folder") one_v['isLeaf'] = True print("res_dict second for: {}".format(res_dict)) res_dict_two = copy.deepcopy(res_dict) # 递归遍历children的数据,如果children中数据在列表第一层中,则删掉第一层的对应数据 for sec_k, sec_v in res_dict.items(): children_list = sec_v.get("children") for i in range(len(children_list)): children_ele_id = children_list[i].get("id") if children_ele_id in res_dict_two.keys(): # print("children_ele_id: {}".format(children_ele_id)) # 直接在res_dict_two中pop掉 res_dict_two.pop(children_ele_id) print("res_dict_two: {}".format(res_dict_two)) res_list = list(res_dict_two.values()) return res_list