Node.js实现SQL Server菜单数据树形结构展示方案问询
扁平菜单转树形结构的实现方法
核心思路
- 先建立父ID与子节点的映射表,快速定位每个节点的子项
- 筛选出所有根节点(根据你的
AUT_MENU表定义,通常是parentId为0、null或-1的节点) - 通过递归或迭代的方式,为每个节点添加
children属性,填充对应的子节点
基础递归实现代码
假设你的扁平菜单数据结构如下(字段名可根据实际表结构调整):
// 示例扁平菜单数据 const flatMenus = [ { id: 1, parentId: 0, name: '系统管理', path: '/system' }, { id: 2, parentId: 1, name: '用户管理', path: '/system/users' }, { id: 3, parentId: 1, name: '角色管理', path: '/system/roles' }, { id: 4, parentId: 0, name: '内容管理', path: '/content' }, { id: 5, parentId: 4, name: '文章管理', path: '/content/articles' } ]; function buildTree(flatData, parentKey = 'parentId', idKey = 'id', childrenKey = 'children') { // 1. 构建父ID到子节点的映射 const parentMap = {}; flatData.forEach(item => { const parentId = item[parentKey]; if (!parentMap[parentId]) parentMap[parentId] = []; parentMap[parentId].push({ ...item, [childrenKey]: [] }); }); // 2. 获取根节点(此处假设parentId=0为根,需根据你的表结构调整) const rootNodes = parentMap[0] || []; // 3. 递归填充子节点 function fillChildren(nodes) { nodes.forEach(node => { const children = parentMap[node[idKey]] || []; node[childrenKey] = children; fillChildren(children); }); } fillChildren(rootNodes); return rootNodes; } // 使用示例 const treeMenus = buildTree(flatMenus); console.log(JSON.stringify(treeMenus, null, 2));
大数据量适配:迭代实现(避免递归栈溢出)
如果菜单数据量很大,递归可能导致栈溢出,改用队列迭代的方式更稳妥:
function buildTreeIterative(flatData, parentKey = 'parentId', idKey = 'id', childrenKey = 'children') { const parentMap = {}; const nodeMap = {}; // 先把所有节点存入映射表,初始化children数组 flatData.forEach(item => { nodeMap[item[idKey]] = { ...item, [childrenKey]: [] }; const parentId = item[parentKey]; if (!parentMap[parentId]) parentMap[parentId] = []; parentMap[parentId].push(item[idKey]); }); // 获取根节点 const rootIds = parentMap[0] || []; const rootNodes = rootIds.map(id => nodeMap[id]); // 用队列迭代填充子节点 const queue = [...rootNodes]; while (queue.length > 0) { const currentNode = queue.shift(); const childIds = parentMap[currentNode[idKey]] || []; childIds.forEach(id => { const childNode = nodeMap[id]; currentNode[childrenKey].push(childNode); queue.push(childNode); }); } return rootNodes; }
实用注意事项
- 根节点判断:根据
AUT_MENU表的实际定义调整,比如有的表用parentId = null或parentId = -1表示根节点,只需修改parentMap[0]对应的键即可 - 字段适配:如果你的表字段不是
id/parentId,比如是menuId/parentMenuId,调用时传入对应参数:buildTree(flatMenus, 'parentMenuId', 'menuId') - 调试技巧:转换前可以
console.log(parentMap),检查父ID与子节点的映射是否正确建立
内容的提问来源于stack exchange,提问作者kenny
相关产品推荐
相关产品推荐

