【JavaScript】 获取树被选中的顶级节点(小记)
1. 若存在一棵树
例如:
const tree = [
{
id: '1',
children: [
{
id: '1-1',
children: [
{
id: '1-1-1',
children: [
{
id: '1-1-1-1',
children: []
},
{
id: '1-1-1-2',
children: []
},
{
id: '1-1-1-3',
children: []
}
]
}
]
},
{
id: '1-2',
children: [
{
id: '1-2-1',
children: []
}
]
}
]
},
{
id: '2',
children: [
{
id: '2-1',
children: [
{
id: '2-1-1',
children: []
}
]
},
{
id: '2-2',
children: [
{
id: '2-2-1',
children: []
}
]
}
]
}
]
2. 期望结果
lookAtCheckedTopNodes(['1', '2'], tree) // => ['1', '2']
lookAtCheckedTopNodes(['1-1-1-1', '1-1-1-2', '1-1-1-3'], tree) // => ['1-1']
lookAtCheckedTopNodes(['1-1-1-1', '1-1-1-2', '1-1-1-3', '1-2'], tree) // => ['1']
lookAtCheckedTopNodes(['1-1-1-1', '1-1-1-2', '1-1-1-3', '1-2-1'], tree) // => ['1']
lookAtCheckedTopNodes(['1-1', '1-2'], tree) // => ['1']
3. 实现
function getCheckNodeAndParent(checked = [], tree = []) {
const loop = (tree, parent = null, map = {}) => {
for (const item of tree) {
item.parent = parent
if (checked.includes(item.id)) {
map[item.id] = item
continue
}
if (item.children && item.children.length) {
const newMap = loop(item.children, item, map)
map = { ...map, ...newMap }
}
}
return map
}
return loop(tree)
}
function loopLookParent(map) {
// 递归重新遍历map,找到所有的父节点
const newMap = {}
let flag = false
for (const key in map) {
const item = map[key]
const { parent } = item
if (!parent) {
newMap[key] = item
continue
}
const { id, children } = parent
const parentChildrenCheckedAll = children?.every((child) => map[child.id])
if (parentChildrenCheckedAll) {
flag = true
newMap[id] = parent
} else {
newMap[key] = item
}
}
if (flag) {
return loopLookParent(newMap)
}
return newMap
}
export function lookAtCheckedTopNodes(checked = [], tree = []) {
const map = getCheckNodeAndParent(checked, tree)
return loopLookParent(map)
}
为之则易,不为则难。