目录
完整代码和结果
const arr = [ { name: '内容1', fid: 0, id: 0, }, { name: '内容2', fid: 0, id: 1, }, { name: '内容3', fid: 0, id: 2, }, { name: '内容4', fid: 1, id: 3, }, { name: '内容5', fid: 1, id: 4, }, { name: '内容6', fid: 2, id: 5, }, ] const res = [] // 两个入参 一个是线性对象数组,一个是目标对象 const addChild = (arr, obj) => { // 目标对象的fid const { fid } = obj // 遍历线性对象数组 arr.forEach(cur => { // 取出遍历的对象的id const { id } = cur // 判断是否是目标对象的fid if (fid === id) { // 如果是,先判断加上child指针 cur.child ? null : cur.child = [] // 如果加过了,直接加进子级数组 cur.child.push(obj) } else if (cur.child) { // 存在子级对象数组,就得判断子级有没有 addChild(cur.child, obj) } }); } arr.map(cur => { const { id, fid } = cur if (id === fid) { res.push(cur) } else { addChild(res, cur) } }) console.log(res)
思想理解
创建线性数据
在创建线性数据时我们就应该为树状数据的转化做准备,什么准备呢?
const arr = [ { name: '内容1', fid: 0, id: 0, }, { name: '内容2', fid: 0, id: 1, }, { name: '内容3', fid: 0, id: 2, }, { name: '内容4', fid: 1, id: 3, }, { name: '内容5', fid: 1, id: 4, }, { name: '内容6', fid: 2, id: 5, }, ]
比如我创造一个这样的数据,fid表示它父级节点的id。
特点就是id按顺序排列,且父节点的id会小于子节点的id。
这样我们就可以很容易的生成树状结构,不必担心自己的父级节点比自己晚遍历到,不会造成找不到父级节点的情况。
创建一个结果数组
const res = []
找到根节点
我们创建了结果数组,树也许不好整,但是把根种下去还是容易吧。
比如你可以提前标好type,我这里是定义自己id与fid相等的为根节点。
我们遍历数据,把定义好的根加入
arr.map(cur => { const { id, fid } = cur if (id === fid) { res.push(cur) } else { ... } })
接下来就是考虑…到底是什么呢,如果不是根,那这个目标对象就是有父节点的了。
既然有父节点,我们就把结果数组遍历一遍找找有没有对应的目标对象的父节点。
我们就需要创建一个找父级的方法。
可能需要两个入参,一个结果数组也就是一个对象数组,和一个正在找父级的目标对象
addChild(arr,obj)
创建递归方法
我们希望在一个线性的对象数组里找到其中的一个对象,是我们某个目标对象的父级节点。
如果是找到了,就给父级节点加入子级指针指向目标对象。
// 两个入参 一个是线性对象数组,一个是目标对象 const addChild = (arr, obj) => { // 目标对象的fid const { fid } = obj // 遍历线性对象数组 arr.forEach(cur => { // 取出遍历的对象的id const { id } = cur // 判断是否是目标对象的fid if (fid === id) { // 如果是,先判断加上child指针 cur.child ? null : cur.child = [] // 如果加过了,把目标对象直接加进遍历对象的子级数组 cur.child.push(obj) } }); }
如果不是呢?不是的话就不加了吗,肯定不行。
因为即便当前的遍历对象不是目标对象的父级节点,我们不能保证遍历对象的子级对象数组中没有目标对象的节点。
那么怎么判断子级对象数组有没有呢?
我们发现又是在一个对象数组里面找,所以我们还是调用同样的方法,这就是递归了。
// 两个入参 一个是线性对象数组,一个是目标对象 const addChild = (arr, obj) => { // 目标对象的fid const { fid } = obj // 遍历线性对象数组 arr.forEach(cur => { // 取出遍历的对象的id const { id } = cur // 判断是否是目标对象的fid if (fid === id) { // 如果是,先判断加上child指针 cur.child ? null : cur.child = [] // 如果加过了,直接加进子级数组 cur.child.push(obj) } else if (cur.child) { // 存在子级对象数组,就得判断子级有没有 addChild(cur.child, obj) } }); }