处理树数据
前言
在工作中,经常需要处理树数据,自己总结了部分处理数据的函数,如下:
代码
tree.json
[
{ "id": "4", "pid": "1", "name": "大家电" },
{ "id": "5", "pid": "1", "name": "生活电器" },
{ "id": "1", "pid": "0", "name": "家用电器" },
{ "id": "2", "pid": "0", "name": "服饰" },
{ "id": "3", "pid": "0", "name": "化妆" },
{ "id": "7", "pid": "4", "name": "空调" },
{ "id": "8", "pid": "4", "name": "冰箱" },
{ "id": "9", "pid": "4", "name": "洗衣机" },
{ "id": "10", "pid": "4", "name": "热水器" },
{ "id": "11", "pid": "3", "name": "面部护理" },
{ "id": "12", "pid": "3", "name": "口腔护理" },
{ "id": "13", "pid": "2", "name": "男装" },
{ "id": "14", "pid": "2", "name": "女装" },
{ "id": "15", "pid": "7", "name": "海尔空调" },
{ "id": "16", "pid": "7", "name": "美的空调" },
{ "id": "19", "pid": "5", "name": "加湿器" },
{ "id": "20", "pid": "5", "name": "电熨斗" }
]
tree.js
/**
* 深拷贝
*/
const deepClone = (obj) => {
function isObject (obj) {
return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}
if (!isObject(obj)) {
throw new Error('非对象')
}
let isArray = Array.isArray(obj)
let newObj = isArray ? [...obj] : {...obj}
Reflect.ownKeys(obj).forEach(key => {
newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
})
return newObj
}
/**
* 将树数据扁平化
* @param {Array} data 树数据数组
*/
const treeFlatten = (data = []) => {
return data.reduce((prev, {children, ...res}) => prev.concat([res], treeFlatten(children || [])), [])
// return data.reduce((prev, {children, ...res}) => [...prev, res, ...treeFlatten(children || [])], [])
}
/**
* 获取树节点的所有直系祖先节点
* @param {Array} data 扁平化后的树数据
* @param {Number | String} id 单个树节点id
* @param {Array} res 返回数组
*/
const getTreeAncestor = (data = [], id, key_id = 'id', key_pid = 'pid') => {
const res = []
let temp = data.find(v => v[key_id] === id)
while (temp) {
res.push(temp[key_id])
temp = data.find(v => v[key_id] === temp[key_pid])
}
return res
}
/**
* 组装树数据
*
* @param {Array} data
* @returns
*/
const toTree = (data = [], key_id = 'id', key_pid = 'pid') => {
const d = deepClone(data)
const temp = d.reduce((prev, next) => {
prev[next[key_id]] = next
return prev
}, {})
const arr = []
for (let i = 0; i < d.length; i++) {
const item = d[i]
const hasParent = temp[item[key_pid]]
if (hasParent) {
if (!hasParent.children) {
hasParent.children = []
}
hasParent.children.push(item)
} else {
arr.push(item)
}
}
return arr
}
// 读取树数据(getJson函数未定义,请自行从tree.json中赋值给arr)
let arr = getJson('./tree.json')
let tree = toTree(arr)
console.log('tree is ', tree)
let findAn = getTreeAncestor(arr, '19')
console.log('findAn is ', findAn)
let flatTree = treeFlatten(tree)
console.log('flatTree is ', flatTree)