菜单数组转换为嵌套树形结构

219 阅读2分钟

为了将给定的扁平化菜单数组转换为嵌套树形结构,我们需要遍历数组并构建一个映射,以便我们可以根据parentId快速找到父节点。然后,我们可以再次遍历数组,将每个项目添加到其对应的父节点的children数组中(如果父节点存在)。

以下是一个简单的JavaScript函数,它实现了这种转换:

function flattenToTree(items) {
  // 创建一个映射,用于快速查找具有给定id的节点
  const map = new Map();
  items.forEach((item) => map.set(item.id, { ...item, children: [] }));

  // 遍历所有节点,如果它们有parentId,则将它们添加到其父节点的children数组中
  items.forEach((item) => {
    if (item.parentId) {
      // 确保父节点存在
      const parent = map.get(item.parentId);
      if (parent) {
        parent.children.push(map.get(item.id));
      }
    }
  });

  // 提取所有顶级节点(没有parentId的节点)
  return [...map.values()].filter((item) => !item.parentId);
}

// 示例数据
const menuItems = [
  { id: 1, menu: "水果", level: 1 },
  { id: 2, menu: "橘子", level: 2, parentId: 1 },
  // 可以添加更多菜单项...
];

// 调用函数并打印结果
const tree = flattenToTree(menuItems);
console.log(tree);

当你运行上述代码时,它应该输出类似于以下内容的树形结构:

[  
  {  
    "id": 1,  
    "menu": "水果",  
    "level": 1,  
    "children": [  
      {  
        "id": 2,  
        "menu": "橘子",  
        "level": 2,  
        "parentId": 1,  
        "children": []  
      }  
      // ... 其他子菜单项(如果有的话)  
    ]  
  }  
  // ... 其他顶级菜单项(如果有的话)  
]

请注意,这个函数假设id是唯一的,并且每个节点的parentId(如果存在)都引用了一个已存在的id。如果这不是情况,你可能需要添加额外的错误处理来避免未定义的行为。

当然,我们可以使用更多层次的数据来测试这个函数。以下是一个包含三个层次(顶级、一级子菜单、二级子菜单)的示例数据:

const menuItems = [  
  { id: 1, menu: '食品', level: 1 },  
  { id: 2, menu: '水果', level: 2, parentId: 1 },  
  { id: 3, menu: '蔬菜', level: 2, parentId: 1 },  
  { id: 4, menu: '柑橘类', level: 3, parentId: 2 },  
  { id: 5, menu: '绿叶蔬菜', level: 3, parentId: 3 },  
  // 还可以继续添加更多菜单项...  
];  
  
// 使用前面定义的 flattenToTree 函数  
const tree = flattenToTree(menuItems);  
console.log(tree);

运行上述代码后,应该得到如下输出(格式化后的JSON结构):

[  
  {  
    "id": 1,  
    "menu": "食品",  
    "level": 1,  
    "children": [  
      {  
        "id": 2,  
        "menu": "水果",  
        "level": 2,  
        "parentId": 1,  
        "children": [  
          {  
            "id": 4,  
            "menu": "柑橘类",  
            "level": 3,  
            "parentId": 2,  
            "children": []  
          }  
        ]  
      },  
      {  
        "id": 3,  
        "menu": "蔬菜",  
        "level": 2,  
        "parentId": 1,  
        "children": [  
          {  
            "id": 5,  
            "menu": "绿叶蔬菜",  
            "level": 3,  
            "parentId": 3,  
            "children": []  
          }  
        ]  
      }  
      // ... 其他一级子菜单项(如果有的话)  
    ]  
  }  
  // ... 其他顶级菜单项(如果有的话)  
]

如你所见,flattenToTree 函数能够正确处理多层次的数据结构,并将其转换为嵌套的树形结构。每个节点都有一个 children 数组,用于包含其所有子节点。如果某个节点没有子节点,则其 children 数组将为空。