来源数据结构
const productInfoList = [{
productId: 2,
productName: '2',
parentId: 1
},{
productId: 1,
productName: '1',
parentId: ''
},{
productId: 3,
productName: '3',
parentId: 2
},{
productId: 4,
productName: '4',
parentId: ''
}]
// ...无限层级,父子乱序
目标期望数据结构
const target = [{
label: '1',
id: 1,
children: [{
label: '2',
id: 2,
children: [{
label: '3',
id: 3,
children: []
}]
}]
},{
label: '4',
id: 4,
children: []
}]
业务逻辑
const infinite = (id, target = this.product.menu, source = productInfoList) => {
for (const i in source) {
if (source[i].parentId === id) {
target.push({
label: source[i].productName,
id: source[i].productId,
children: []
})
infinite(source[i].productId, target[target.length - 1].children)
}
}
}
infinite('') // 已知根节点id为 ''
// 无限层级,乱序数组,未知根节点
const source = [{
productId: 2,
name: '2',
parentId: 1
}, {
productId: 1,
name: '1',
parentId: 99
}, {
productId: 4,
name: '4',
parentId: ''
}, {
productId: 6,
name: '6',
parentId: 1
}, {
productId: 3,
name: '3',
parentId: 1
}, {
productId: 7,
name: '7',
parentId: 2
}, {
productId: 8,
name: '8',
parentId: 66
}, {
productId: 5,
name: '5',
parentId: 4
}]
const infiniteLevel = {
init(source, formate) {
this.target = [] // 用于临时存储结果
this.source = source // 用户来源集合
this.formateSub = formate || function() {} // 用户自定义格式化内容
for (const index in this.source) {
this.infinite(this.source[index], index) // 开始无限递归遍历,index参数用于判断是init执行的infinite还是自己递归执行的
}
return this.setResult() // 返回最终结果
},
formate(item) { // 用于格式化每一项,根据项目实际需求设置
const sub = this.formateSub(item)
return Object.assign({
label: item.name,
id: item.id,
pid: item.pid,
level: item.level || 0,
children: item.children || []
}, sub)
},
infinite(item, index) {
const result = this.formate(item)
if (index === undefined) result.level ++ // index用于判断level,如果有index就证明是第一次开始计算层级,如果是undefined就是递归来的叠加层级。
let isParent = null
const children = []
this.source.forEach(s => {
const formateS = this.formate(s)
if (formateS.id === result.pid) isParent = s // 判断每一项的父级是否存在,由于来源中的id可能不存在,要先进行格式化。
if (formateS.pid === result.pid) children.push(formateS) // 找到所有的同级
})
if (isParent) { // 如果父级存在继续递归向上寻找祖父级直至根级
isParent.children = children // 将刚刚获取到的所有子集放入该父级节点下
isParent.level = result.level // 新增level属性,用于判断该父级存在几级子节点,用于最后找到包含层级最多的父级,也就是根级。
this.infinite(isParent)
} else {
this.target.push(result)
}
},
setResult() {
const result = []
this.target.sort((a, b) => {
return b.level - a.level
}).forEach(e => {
if (!result.some(r => r.id === e.id) && !isNaN(e.level)){
result.push(e)
}
})
return result
}
}
console.log(infiniteLevel.init(source, (item) => {
return {
id: item.productId,
pid: item.parentId
}
}))