vue的自定义树形列表组件(及数据格式转换)
- 组件定义
子组件:
- 以下内容为普通扁平化格式转换成树形对象的方法
- 其中list的格式为
-
[
{
"id": 100,
"pId": 0,
"name": "科技",
"title": "科技",
"checked": false,
"open": false,
"nocheck": false
},
{
"id": 101,
"pId": 100,
"name": "深圳总公司",
"title": "深圳总公司",
"checked": false,
"open": false,
"nocheck": false
},
{
"id": 102,
"pId": 100,
"name": "长沙分公司",
"title": "长沙分公司",
"checked": false,
"open": false,
"nocheck": false
},
{
"id": 103,
"pId": 101,
"name": "研发部门",
"title": "研发部门",
"checked": false,
"open": false,
"nocheck": false
},
{
"id": 104,
"pId": 101,
"name": "市场部门",
"title": "市场部门",
"checked": false,
"open": false,
"nocheck": false
},
{
"id": 105,
"pId": 101,
"name": "测试部门",
"title": "测试部门",
"checked": false,
"open": false,
"nocheck": false
},
{
"id": 106,
"pId": 101,
"name": "财务部门",
"title": "财务部门",
"checked": false,
"open": false,
"nocheck": false
},
{
"id": 107,
"pId": 101,
"name": "运维部门",
"title": "运维部门",
"checked": false,
"open": false,
"nocheck": false
},
{
"id": 108,
"pId": 102,
"name": "市场部门",
"title": "市场部门",
"checked": false,
"open": false,
"nocheck": false
},
{
"id": 109,
"pId": 102,
"name": "财务部门",
"title": "财务部门",
"checked": false,
"open": false,
"nocheck": false
}
] -
buildTree(list){let pidStr = 'pId';let idStr = 'id';let childrenStr = 'children';
let listOjb = {}; // 用来储存{key: obj}格式的对象let treeList = []; // 用来储存最终树形结构数据的数组
// 将数据变换成{key: obj}格式,方便下面处理数据for (let i = 0; i < list.length; i++) {listOjb[list[i][idStr]] = list[i]}
for (let j = 0; j < list.length; j++) {// 判断父级是否存在let haveParent = listOjb[list[j][pidStr]]if (haveParent) {// 如果有没有父级children字段,就创建一个children字段!haveParent[childrenStr] && (haveParent[childrenStr] = [])// 在父级里插入子项haveParent[childrenStr].push(list[j])} else {// 如果没有父级直接插入到最外层treeList.push(list[j])}}return treeList},
实现算法buildTree
算法思想:
先将数组中的每一个节点放到temp对象中(创建map)
即数组中有{id: '2-3', parent_id: '2',...}这样一个节点,需要将他放到temp中变成 '2-3': {id: '2-3', parent_id: '2',...}这种JSON结构
直接遍历整个temp对象,通过这句代码 temp[temp[i].parent_id].children[temp[i].id] = temp[i]; 将当前子节点与父节点建立连接。是因为我们保证了父节点一定在子节点前,那么当子节点出现的时候就直接可以用temp[temp[i].parent_id]来查找到父节点这个时候先父节点的children对象中添加一个引用即可。
/**
* 将一维的扁平数组转换为多层级对象
* @param {[type]} list 一维数组,数组中每一个元素需包含id和parent_id两个属性
* @return {[type]} tree 多层级树状结构
*/
function buildTree(list){
let temp = {};
let tree = {};
for(let i in list){
temp[list[i].id] = list[i];
}
for(let i in temp){
if(temp[i].parent_id) {
if(!temp[temp[i].parent_id].children) {
temp[temp[i].parent_id].children = new Object();
}
temp[temp[i].parent_id].children[temp[i].id] = temp[i];
} else {
tree[temp[i].id] = temp[i];
}
}
return tree;
}
测试结果:
可以看到函数成功地构建了多级的树状结构
这个算法的效率是极高的,比多重for循环来的好得多。
以下是测试数据,用时只需5毫秒左右:
var menu_list = [{
id: '1',
menu_name: '设置',
menu_url: 'setting',
parent_id: 0
}, {
id: '1-1',
menu_name: '权限设置',
menu_url: 'setting.permission',
parent_id: '1'
}, {
id: '1-1-1',
menu_name: '用户管理列表',
menu_url: 'setting.permission.user_list',
parent_id: '1-1'
}, {
id: '1-1-2',
menu_name: '用户管理新增',
menu_url: 'setting.permission.user_add',
parent_id: '1-1'
}, {
id: '1-1-3',
menu_name: '角色管理列表',
menu_url: 'setting.permission.role_list',
parent_id: '1-1'
}, {
id: '1-1-4',
menu_name: '角色管理新增',
menu_url: 'setting.permission.role_add',
parent_id: '1-1'
}, {
id: '1-2',
menu_name: '菜单设置',
menu_url: 'setting.menu',
parent_id: '1'
}, {
id: '1-2-1',
menu_name: '菜单列表',
menu_url: 'setting.menu.menu_list',
parent_id: '1-2'
}, {
id: '1-2-2',
menu_name: '菜单添加',
menu_url: 'setting.menu.menu_add',
parent_id: '1-2'
}, {
id: '2',
menu_name: '订单',
menu_url: 'order',
parent_id: 0
}, {
id: '2-1',
menu_name: '报单审核',
menu_url: 'order.orderreview',
parent_id: '2'
}, {
id: '2-2',
menu_name: '退款管理',
menu_url: 'order.refundmanagement',
parent_id: '2'
}, {
id: '2-3',
menu_name: '实物订单',
menu_url: 'order.realorder',
parent_id: '2'
}, {
id: '2-1-1',
menu_name: '全部报单',
menu_url: 'order.orderreview.all',
parent_id: '2-1'
}, {
id: '2-2-1',
menu_name: '所有记录',
menu_url: 'order.refundmanagement.all',
parent_id: '2-2'
}, {
id: '2-2-2',
menu_name: '待处理',
menu_url: 'order.refundmanagement.wait',
parent_id: '2-2'
}, {
id: '2-2-3',
menu_name: '退款原因',
menu_url: 'order.refundmanagement.result',
parent_id: '2-2'
}, {
id: '2-3-1',
menu_name: '实物订单管理',
menu_url: 'order.realorder.list',
parent_id: '2-3'
}, {
id: '3',
menu_name: '商品',
menu_url: 'commodity',
parent_id: 0
}, {
id: '3-1',
menu_name: '分类管理',
menu_url: 'commodity.classifieldmanagement',
parent_id: '3'
}, {
id: '3-1-1',
menu_name: '管理',
menu_url: 'commodity.classifieldmanagement.management',
parent_id: '3-1'
}, {
id: '3-1-2',
menu_name: '编辑或新增',
menu_url: 'commodity.classifieldmanagement.edit',
parent_id: '3-1'
}, {
id: '3-2',
menu_name: '品牌管理',
menu_url: 'commodity.brandmanagement',
parent_id: '3'
}, {
id: '3-2-1',
menu_name: '管理',
menu_url: 'commodity.brandmanagement.management',
parent_id: '3-2'
}, {
id: '3-2-2',
menu_name: '编辑或新增',
menu_url: 'commodity.brandmanagement.edit',
parent_id: '3-2'
}, {
id: '3-3',
menu_name: '商品管理',
menu_url: 'commodity.commoditymanagement',
parent_id: '3'
}, {
id: '3-3-1',
menu_name: '管理',
menu_url: 'commodity.commoditymanagement.management',
parent_id: '3-3'
}, {
id: '3-3-2',
menu_name: '编辑或新增',
menu_url: 'commodity.commoditymanagement.edit',
parent_id: '3-3'
}, {
id: '3-4',
menu_name: '类型管理',
menu_url: 'commodity.typeManagement',
parent_id: '3'
}, {
id: '3-4-1',
menu_name: '管理',
menu_url: 'commodity.typeManagement.management',
parent_id: '3-4'
}, {
id: '3-4-2',
menu_name: '编辑或新增',
menu_url: 'commodity.typeManagement.edit',
parent_id: '3-4'
}]