转树形结构、遍历树形结构、扁平树形

这篇就是写一下平级结构与树形结构之间的转化,之前也有写过类似的:
对象数组转为树形结构
js树形结构,根据里层id找出它所属的每层父级集合
大家有兴趣可以去看一下,也算是简单巩固一下js吧

1. 对象数组转为树形结构 

① 常见格式 

一般如果平级的数组结构可以转化为树形,都会有id和parentId两个字段来标识子级和父级,来确定关系

测试数据 
let source = [
  {
    title: '角色编辑',
    parentId: 22,
    id: 222,
  },
  {
    title: '系统管理',
    parentId: 0,
    id: 1,
  },
  {
    title: '角色新增',
    parentId: 22,
    id: 221,
  },
  {
    title: '角色删除',
    parentId: 22,
    id: 223,
  },
  {
    title: '用户新增',
    parentId: 33,
    id: 331,
  },
  {
    title: '菜单新增',
    parentId: 11,
    id: 111,
  },
  {
    title: '菜单编辑',
    parentId: 11,
    id: 112,
  },
  {
    title: '用户管理',
    parentId: 0,
    id: 33,
  },
  {
    title: '菜单管理',
    parentId: 1,
    id: 11,
  },
  {
    title: '菜单删除',
    parentId: 11,
    id: 113,
  },
  {
    title: '用户编辑',
    parentId: 33,
    id: 332,
  },
  {
    title: '角色管理',
    parentId: 1,
    id: 22,
  },
  {
    title: '用户删除',
    parentId: 33,
    id: 333,
  }
]
 方法:
function toTree(list, id = 'id', pid = 'parentId', childrenKey = 'children') {
  const target = []
  const map = {}
  list.forEach(item => {
    map[item[id]] = item
  })
  list.forEach(item => {
    let parent = map[item[pid]]
    if (parent) {
      (parent[childrenKey] || (parent[childrenKey] = [])).push(item)
    } else {
      target.push(item)
    }
  })
  return target
}
② 不常见格式 

这种也是平级结构,但是给你的全部是叶子节点,每条数据里面都包含了他上级的id和name,一般这种都会确定有几级 

就想下面这个测试数据就是,返回了所有的人员信息,每条人员数据里面都包含了他所属的单位(一级)的id(unitId)和name(unitName)、以及他所属的部门(二级)的id (deptId)和name(deptName)。然后将其构建出一个树形数据来

 测试数据
let data = [
	{
		imageUrl: 'c://image/1.jpg',
		employeeId: '100000',
		employeeName: '张三',
		employeeGender: 0,
		deptId: 0,
		deptName: '软件',
		unitId: 0,
		unitName: '山东分院',
		phoneNum: '18366666666',
		accountBalance: null,
		email: '1@cmdi.com',
		isOwn: 0,
		employeeStatus: 0,
		queryString: null,
	},
	{
		imageUrl: 'c://image/1.jpg',
		employeeId: '100001',
		employeeName: '小王',
		employeeGender: 0,
		deptId: 1,
		deptName: '测试',
		unitId: 0,
		unitName: '山东分院',
		phoneNum: '18366666666',
		accountBalance: null,
		email: '1223145@cmdi.com',
		isOwn: 0,
		employeeStatus: 0,
		queryString: null,
	},
	{
		imageUrl: 'c://image/1.jpg',
		employeeId: '100002',
		employeeName: '李四',
		employeeGender: 0,
		deptId: 2,
		deptName: '测试',
		unitId: 1,
		unitName: '信通子公司',
		phoneNum: '18366666666',
		accountBalance: null,
		email: '3123145@cmdi.com',
		isOwn: 0,
		employeeStatus: 0,
		queryString: null,
	},
	{
		imageUrl: 'c://image/1.jpg',
		employeeId: '100003',
		employeeName: '小李',
		employeeGender: 0,
		deptId: 3,
		deptName: '开发',
		unitId: 1,
		unitName: '信通子公司',
		phoneNum: '18366666666',
		accountBalance: null,
		email: '1234145@cmdi.com',
		isOwn: 0,
		employeeStatus: 0,
		queryString: null,
	},
	{
		imageUrl: 'c://image/1.jpg',
		employeeId: '100004',
		employeeName: '王五',
		employeeGender: 0,
		deptId: 1,
		deptName: '测试',
		unitId: 0,
		unitName: '山东分院',
		phoneNum: '18366666666',
		accountBalance: null,
		email: '1231545@cmdi.com',
		isOwn: 0,
		employeeStatus: 0,
		queryString: null,
	},
]
 方法:
function useUnitDeptEmpTree(emps) {
	const tree = []
	for (let emp of emps) {
		if (!emp.id) {
			emp.id = getUuid()
		}
		emp.name = emp.employeeName
		let unit = tree.find(item => item.id == emp.unitId)
		if(!unit) {
			unit = { id: emp.unitId, name: emp.unitName, children: [] }
			tree.push(unit)
		}
		let dept = unit.children.find(item => item.id == emp.deptId)
		if(!dept) {
			dept = { id: emp.deptId, name: emp.deptName, children: [] }
			unit.children.push(dept)
		}
		dept.children.push(emp)
	}
	return tree
}


function getUuid() {
  const temp_url = URL.createObjectURL(new Blob())
  const uuid = temp_url.toString()
  URL.revokeObjectURL(temp_url) //释放这个url
  return uuid.substring(uuid.lastIndexOf('/') + 1)
}

2. 遍历树形结构、扁平树形 

就是我们现在有个树形结构,如何遍历到整个树形的每一项呢,也同样的肯定会有个标识子节点的属性,例如:children,然后我们可以通过递归和forEach方法即可遍历整个树形,为了更方便起见,我们可以传递一个callback回调函数,这样遍历到每个节点的时候可以更方便的写一些自己的逻辑,就像forEach似的,工具函数如下:

 测试数据
let tree = [
  {
    "title": "系统管理",
    "parentId": 0,
    "id": 1,
    "children": [
      {
        "title": "菜单管理",
        "parentId": 1,
        "id": 11,
        "children": [
          {
            "title": "菜单新增",
            "parentId": 11,
            "id": 111
          },
          {
            "title": "菜单编辑",
            "parentId": 11,
            "id": 112
          },
          {
            "title": "菜单删除",
            "parentId": 11,
            "id": 113
          }
        ]
      },
      {
        "title": "角色管理",
        "parentId": 1,
        "id": 22,
        "children": [
          {
            "title": "角色编辑",
            "parentId": 22,
            "id": 222
          },
          {
            "title": "角色新增",
            "parentId": 22,
            "id": 221
          },
          {
            "title": "角色删除",
            "parentId": 22,
            "id": 223
          }
        ]
      }
    ]
  },
  {
    "title": "用户管理",
    "parentId": 0,
    "id": 33,
    "children": [
      {
        "title": "用户新增",
        "parentId": 33,
        "id": 331
      },
      {
        "title": "用户编辑",
        "parentId": 33,
        "id": 332
      },
      {
        "title": "用户删除",
        "parentId": 33,
        "id": 333
      }
    ]
  }
]
 方法:
function mapTree(treeData, callback, childrenKey = 'children', level = 0) {
  treeData.forEach(item => {
    const curItem = JSON.parse(JSON.stringify(item))
    curItem.level = level
    callback(curItem, treeData)
    if(item?.[childrenKey]?.length) {
      mapTree(item[childrenKey], callback, childrenKey, level + 1)
    }
  })
}

这里举个例子:就是我们想扁平整个树形,就可以使用上面的工具方法 

let list = []
mapTree(tree, item => {
  if(item.children) delete item.children
  list.push(item)
})
console.log(list)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会说法语的猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值