废话少说,直接上代码。
class Tree {
static default_key = 'id'; // 关键key
static default_parentKey = 'parentId'; // 关键key的父key
static default_initial = '0'; // 祖宗key的值
constructor(
{
list,
key = Tree.default_key,
parentKey = Tree.default_parentKey,
initial = Tree.default_initial,
}) {
this.key = key;
this.parentKey = parentKey;
this.initial = initial;
this.data = this.listToTree(list);
this.setLevelIndex(this.data);
this.list = list;
}
// list转化tree
listToTree(list) {
list.forEach(c => {
c.children = []
list.forEach(d => {
if (c[this.key] === d[this.parentKey]) {
c.children.push(d);
}
})
});
return list.filter(c => c[this.parentKey] === this.initial);
}
// 根据id找到对应节点
findNode(id) {
let result = null
const handle = (id = id, data = this.data) => {
if (data.length) {
for (let i = 0; i < data.length; i++) {
if (data[i][this.key] === id) {
result = data[i];
break;
} else {
handle(id, data[i].children);
}
}
}
}
handle(id);
return result;
}
// 根据id找到对应节点的父节点
findParentNode(id){
const node = this.findNode(id);
return node ? this.findNode(node[this.parentKey]) : null;
}
// 根据id找到对应节点所有的父节点
findAllParentNode(id) {
let result = [];
const handle = (id) => {
const parentNode = this.findParentNode(id);
if (parentNode) {
result.push(parentNode);
}
if (parentNode && parentNode[this.parentKey] !== this.initial) {
handle(parentNode[this.key]);
}
}
handle(id);
return result;
}
// 根据id找到对应节点的子节点
findChildrenNode(id) {
const node = this.findNode(id);
return node ? node.children : [];
}
// 根据id找到对应节点的路径
findPath(id) {
const node = this.findNode(id);
const allParentNode = this.findAllParentNode(id);
return node ? [node, ...allParentNode].reverse() : [];
}
// 根据id找到对应节点的叶子节点
findLeafNode(id) {
let result = []
const handle = (id) => {
const childrenNode = this.findChildrenNode(id);
if (childrenNode.length) {
childrenNode.forEach(c => {
handle(c[this.key]);
})
} else {
const node = this.findNode(id);
if (node) {
result.push(node);
}
}
}
handle(id);
return result;
}
// 获取树所有叶子节点
findAllLeafNode() {
let result = []
this.data.forEach(c => {
result.push(...this.findLeafNode(c[this.key]))
});
return result;
}
// 获取树的最大深度
findMaxLevel() {
let maxLevel = 0;
this.findAllLeafNode().forEach(c => {
const level = this.findPath(c[this.key]).length;
if (level > maxLevel) {
maxLevel = level;
}
})
return maxLevel;
}
// 遍历树--添加层级level和标记index
setLevelIndex(data = this.data) {
data.forEach((c, index) => {
const level = this.findPath(c[this.key]).length;
c.level = level;
c.index = index;
if (c.children.length) {
this.setLevelIndex(c.children);
}
})
}
// 找到指定level的所有节点
findSameLevelNode(level) {
let result = [];
if ( level > this.findMaxLevel()) {
return result;
}
const handle = (data = this.data) => {
data.forEach(c => {
if (c.level === level) {
result.push(c);
} else {
if (c.children.length) {
handle(c.children)
}
}
})
}
handle(this.data)
return result;
}
// 对指定id的节点进行调整,会对树造成影响
// setNode(id, obj = {}) {
// const node = this.findNode(id);
// const path = this.findPath(id);
// const indexList = path.map(c => c.index);
// let str = `this.data[${indexList[0]}]`
// indexList.forEach((c, i) => {
// if (i > 0) {
// str += `.children[${c}]`
// }
//
// })
// str += `=${JSON.stringify({...node, ...obj})}`
// return eval(str);
// }
}
const list = [
{
id: '0-1', parentId: '0',name: '广东省',
},
{
id: '0-2', parentId: '0',name: '湖南省',
},
{
id: '0-3', parentId: '0',name: '湖北省',
},
{
id: '0-4', parentId: '0',name: '江西省',
},
{
id: '0-1-1', parentId: '0-1',name: '深圳',
},
{
id: '0-1-2', parentId: '0-1',name: '广州',
},
{
id: '0-1-3', parentId: '0-1',name: '汕头',
},
{
id: '0-1-1-1', parentId: '0-1-1',name: '南山区',
},
{
id: '0-1-1-1-1', parentId: '0-1-1-1',name: '粤海街道',
},
{
id: '0-1-1-1-2', parentId: '0-1-1-1',name: '高新街道',
},
{
id: '0-1-1-1-3', parentId: '0-1-1-1',name: '前海街道',
},
{
id: '0-1-1-2', parentId: '0-1-1',name: '福田区',
},
{
id: '0-1-1-3', parentId: '0-1-1',name: '宝安区',
},
{
id: '0-1-2-1', parentId: '0-1-2',name: '天河区',
},
{
id: '0-1-2-2', parentId: '0-1-2',name: '白云区',
},
{
id: '0-1-3-1', parentId: '0-1-3',name: '潮阳区',
},
{
id: '0-2-1', parentId: '0-2',name: '长沙',
},
{
id: '0-2-2', parentId: '0-2',name: '益阳',
},
{
id: '0-2-1-1', parentId: '0-2-1',name: '芙蓉区',
},
{
id: '0-2-1-2', parentId: '0-2-1',name: '天心区',
},
{
id: '0-2-2-1', parentId: '0-2-2',name: '赫山区',
},
{
id: '0-3-1', parentId: '0-3',name: '武汉',
},
{
id: '0-3-2', parentId: '0-3',name: '荆门',
},
{
id: '0-3-3', parentId: '0-3',name: '黄石',
},
{
id: '0-3-1-1', parentId: '0-3-1',name: '江汉区',
},
{
id: '0-3-1-2', parentId: '0-3-1',name: '洪山区',
},
{
id: '0-3-1-3', parentId: '0-3-1',name: '青山区',
},
]
const tree = new Tree({list, key: 'id', parentKey: 'parentId', initial: '0'});
console.log('tree', tree)
console.log(`${tree.findNode('0-1-1-1').name} => findNode => `, tree.findNode('0-1-1-1'));
console.log(`${tree.findNode('0-1-1-1-2').name} => findParentNode => `, tree.findParentNode('0-1-1-1-2'));
console.log(`${tree.findNode('0-1-1-1-2').name} => findParentsNode => `, tree.findAllParentNode('0-1-1-1-2'));
console.log(`${tree.findNode('0-1-1-1').name} => findChildrenNode => `, tree.findChildrenNode('0-1-1-1'));
console.log(`${tree.findNode('0-1-1-1-2').name} => findPath => `, tree.findPath('0-1-1-1-2'));
console.log(`${tree.findNode('0-1').name} => findLeafNode => `, tree.findLeafNode('0-1'));
console.log(`tree所有叶子节点 => findAllLeafNode => `, tree.findAllLeafNode());
console.log(`tree最大深度 => findMaxLevel => `, tree.findMaxLevel());
console.log(`level 2=> findSameLevelNode => `, tree.findSameLevelNode(3));