前端树形结构一般用于网页的地理位置输入框,地理位置级联选择,人员的部门选择等。
常见的做法是使用递归实现树形结构,还有的使用filter函数可直接实现树形结构。
递归:递归函数就是函数对自身的调用,是循环运算的一种算法模式。
经典例子之递归求和:
function sum(n) {
if (n == 1) return 1
return sum(n - 1) + n
}
递归必须由以下两部分组成:
如下实现一个菜单列表的树结构拼接:
let arr = [
{ id: 1, parent: null, text: '菜单1' },
{ id: 11, parent: 1, text: '菜单1-1' },
{ id: 111, parent: 11, text: '菜单1-1-1' },
{ id: 112, parent: 11, text: '菜单1-1-2' },
{ id: 12, parent: 1, text: '菜单1-2' },
{ id: 2, parent: null, text: '菜单2' },
{ id: 21, parent: 2, text: '菜单2-1' },
{ id: 22, parent: 2, text: '菜单2-2' },
];
function getTreeList(rootList, id, list) {
for (item of rootList) {
if (item.parent == id) {
list.push(item);
}
}
for (i of list) {
i.children = [];
getTreeList(rootList, i.id, i.children);
}
return list;
}
let res = getTreeList(arr, null, []);
console.log(res);
数据复杂度O(n^2)
。数据多了时间复杂度爆表。
let cityList = [
{id: 1, parentId: 0, name:'江苏省'},
{id: 2, parentId: 0, name:'广东省'},
{id: 3, parentId: 0, name:'安徽省'},
{id: 4, parentId: 1, name:'苏州市'},
{id: 5, parentId: 1, name:'无锡市'},
{id: 6, parentId: 1, name:'南京市'},
{id: 7, parentId: 2, name:'广州市'},
{id: 8, parentId: 2, name:'深圳市'},
{id: 9, parentId: 3, name:'合肥市'},
{id: 10, parentId: 4, name:'工业园区'},
{id: 11, parentId: 4, name:'吴中区'},
{id: 12, parentId: 4, name:'姑苏区'},
{id: 13, parentId: 9, name:'肥东区'},
{id: 14, parentId: 9, name:'肥西区'},
{id: 15, parentId: 6, name:'江宁区'},
{id: 16, parentId: 6, name:'玄武区'}
];
let treeArr = [];
cityList.forEach(item => {
if(item.parentId === 0){
treeArr.push(item);
}
// 每一项都添加一个children
item.children = cityList.filter(child => child.parentId === item.id);
});
console.log(treeArr);
上面的方案时间复杂度可能有点高,下面是借鉴来的O(n)
解法,可供大家学习参考:
function jsonToTree(arr) {
// 使用map转存,增加查找效率
const map = new Map();
arr.forEach((item) => {
map.set(item.id, item);
});
// 将子元素依次放入父元素中
const res = [];
arr.forEach((item) => {
const parent = map.get(item.parentId);
if (parent) {
(parent.children || (parent.children = [])).push(item);
} else {
res.push(item);
}
});
console.log(res);
}
暂时写这么多,下次优化,如果有大佬优化一下就在评论区指导一下下,谢谢.