新后台做菜单, 👦后端说:
- 这次菜单层级不固定.
- 直接给把数据库中的表数据(数组)发给你.
- 菜单需要排序.
其实平时很少写数据处理, 不过觉得自己差不多能实现就答应了. 写完了觉得还挺好用就分享一下, 🐦菜鸟一枚, 👨路过的大佬如果发现什么问题请告知, 😜我必虚心接受.
注: 饿了么/iview等组件库中的"级联选择器"/"导航菜单"等组件都可使用下面的函数简化操作.
本文源码: github.com/any86/arr2t…
目标
// 🚚 输入数组
const array = [{
id: 1,
name: '蔬菜',
order: 1
},
{
id: 2,
name: '土豆',
pid: 1,
order: 2
}, {
id: 3,
name: '豆角',
pid: 1,
order: 1
}, {
id: 4,
name: '水果',
order: 2
}
];
// 🚀 转换开始
arrayToTree(array);
// 📺输出:
//
// [
// {
// "id": 1,
// "name": "蔬菜",
// "order": 1,
// "children": [
// {
// "id": 3,
// "name": "豆角",
// "pid": 1,
// "order": 1
// },
// {
// "id": 2,
// "name": "土豆",
// "pid": 1,
// "order": 2
// }
// ]
// },
// {
// "id": 4,
// "name": "水果",
// "order": 2
// }
// ]
思路
逻辑很简单, 我一步一步解释下:
- 把"根节点"和其余"子节点"分别存储到2个变量(容器).
- 从根(父)出发, 在"子节点"容器中检查每一个子节点, 找到该父节点对应的子节点, 并存储到父节点对应的children字段中, 不符合的"子节点"继续留到"子节点容器"中.
- 对children字段中的"节点"进行排序(此处排序暂时用的sort).
- 递归执行"步骤2和3"直到"子节点容器"为空.
- 对其他"根节点"重复执行"步骤2/3/4".
代码
/**
* 数组转树
* @param {Array} 输入
* @param {Object.String} keyMap.KEY_ID 表示唯一性键值(id)
* @param {Object.String} keyMap.KEY_PID 对应的父id
* @param {Object.String} keyMap.KEY_ORDER 排序依据的键值
* @returns {Object} 树结构
*/
function arrayToTree(list, keyMap = {
KEY_ID: 'id',
KEY_PID: 'pid',
KEY_ORDER: 'order',
}) {
const {
KEY_ID,
KEY_PID,
KEY_ORDER
} = keyMap;
const roots = [];
// 当前非根节点
let childrenNode = [];
// 分组根和非根节点
list.forEach((item) => {
if (undefined === item[KEY_PID]) {
roots.push(item);
} else {
childrenNode.push(item);
}
});
// 遍历根节点
for (const root of roots) {
findChild(root);
}
// 递归单个根节点
function findChild(root) {
if (0 >= childrenNode.length) return;
let newChildNode = [];
childrenNode.forEach((child) => {
if (root[KEY_ID] === child[KEY_PID]) {
if (undefined === root.children) root.children = [];
root.children.push(child);
findChild(child /**new root */ );
} else {
newChildNode.push(child);
}
});
// 排序
if (undefined !== KEY_ORDER && root.children && 1 < root.children.length) {
root.children = root.children.sort((prev, current) => prev[KEY_ORDER] - current[KEY_ORDER]);
}
childrenNode = newChildNode;
}
return roots;
}
npm & github
本文代码, 我已经存储到github和npm, 可以通过npm进行安装使用.
npm i -S arr2tree
typescript基础教程推荐
最后推下自己写的"typescript基础教程"和😊😊2个基于ts开发的小工具, 希望大家喜欢.
✋ 移动/pc端手势库, 支持: tap/press/pan/swipe/rotate/pinch github.com/any86/any-t…
🍭 把vue组件变成this.$xxx这样的命令 github.com/any86/vue-c…
微信群
感谢大家的阅读, 如有疑问可以加我微信, 我拉你进入微信群(由于腾讯对微信群的100人限制, 超过100人后必须由群成员拉入)