如何利用js层级化数组并封装vue的递归组件实现层级菜单

本文层级化数组的方法借鉴于这位大佬的博客:JavaScript 层级数组常用工具方法(一)—— 数组结构转换_js对象数组转换成4层结构的递归算法-CSDN博客

一、题目:

let arr = [
    { id: 1, father_id: 0, status: 1, name: '数学学院' },
    { id: 2, father_id: 1, status: 1, name: '统计专业' },
    { id: 3, father_id: 2, status: 1, name: '线性代数' },
    { id: 7, father_id: 1, status: 1, name: '应用数学' },
    { id: 8, father_id: 7, status: 1, name: '概率论' },
    { id: 9, father_id: 7, status: 1, name: '微积分应用' },
    { id: 10, father_id: 7, status: 1, name: '运筹学' },
    { id: 11, father_id: 7, status: 1, name: '高等数学' },
    { id: 71, father_id: 1, status: 1, name: '计算专业' },
    { id: 56, father_id: 0, status: 1, name: '信息工程学院' },
    { id: 57, father_id: 56, status: 1, name: '计算结科学与技术' },
    { id: 58, father_id: 56, status: 1, name: '物联网' }
]
请你通过JS函数将以上数据转化为层级结构,如下
[
    {
        "id":1,
        "parentId":0,
        "isEnabled":true,
        "name":"数学学院",
        "_child":[
            {
                "id":2,
                "parentId":1,
                "isEnabled":true,
                "name":"统计专业",
                "_child":[
                    {
                        "id":3,
                        "parentId":2,
                        "isEnabled":true,
                        "name":"线性代数"
                    }
                ]
            },
            {
                "id":7,
                "parentId":1,
                "isEnabled":true,
                "name":"应用数学",
                "_child":[
                    {
                        "id":8,
                        "parentId":7,
                        "isEnabled":true,
                        "name":"概率论"
                    },
                    {
                        "id":9,
                        "parentId":7,
                        "isEnabled":true,
                        "name":"微积分应用"
                    },
                    {
                        "id":10,
                        "parentId":7,
                        "isEnabled":true,
                        "name":"运筹学"
                    },
                    {
                        "id":11,
                        "parentId":7,
                        "isEnabled":true,
                        "name":"高等数学"
                    }
                ]
            },
            {
                "id":71,
                "parentId":1,
                "isEnabled":true,
                "name":"计算专业"
            }
        ]
    },
    {
        "id":56,
        "parentId":0,
        "isEnabled":true,
        "name":"信息工程学院",
        "_child":[
            {
                "id":57,
                "parentId":56,
                "isEnabled":false,
                "name":"计算结科学与技术"
            },
            {
                "id":58,
                "parentId":56,
                "isEnabled":false,
                "name":"物联网"
            }
        ]
    }
]

二、基础数组转化为层级结构数组的方法

方法1:Map

Map概述

Map 对象是键值对的集合,并且能够记住键的原始插入顺序。

任何值(对象或者基本类型)都可以作为一个键或一个值,Map 中的一个键只能出现一次。

 Map中get()和set()的使用方法

// 创建一个空的 Map
let myMap = new Map();

// 设置键值对
myMap.set('key1', 'value1');
myMap.set('key2', 'value2');

// 获取值
console.log(myMap.get('key1')); // 输出: value1

// 检查是否包含某个键
console.log(myMap.has('key2')); // 输出: true

 解决问题

function convertToHierarchy(arr) {
        const map = new Map(); // 使用 Map 存储每个对象,以便通过父ID快速查找
        const result = [];

        // 将每个对象存储到 Map 中
        arr.forEach(item => {
            //判断是否找到有孩子的对象
            let flag = false;
            arr.forEach(element => {
                if (item.id === element.father_id) {
                    //找到有孩子的对象
                    flag = true;
                }
                if (flag) {
                    //初始化有孩子的层级
                    map.set(item.id, { ...item, _child: [] });
                    //找到一个就返回
                    return;
                }
            })
            //遍历完发现没有找到
            if (!flag) {
                //将每个对象的id作为键,剩余内容作为值存储
                map.set(item.id, { ...item });
            }

        });


        // 构建层级结构
        map.forEach(item => {
            //item为map的值
            if (item.father_id === 0) {
                result.push(item); // 如果父ID为0,则为顶级对象
                // console.log(result);
            } else {
                //根据父亲id获取父亲对象的值
                const parent = map.get(item.father_id);
                // console.log(parent);
                //如果对象存在
                if (parent) {
                    parent._child.push(item); // 将子对象添加到父对象的_child数组中
                    // console.log(result);

                }
            }
        });

        return result;
    }

    //将转换后的层级结构数组转换为 JSON 字符串,并使用 4 个空格进行缩进,最后输出结果。
// 第二个参数 null 是可选的 replacer 函数,用于选择性地替换对象的值,我们这里不需要进行替换,所以传入了 null。
    console.log(JSON.stringify(convertToHierarchy(arr), null, 4));

方法2:递归1

优点:简单

缺点:无论有或没有子节点,都会有_child属性

function convertToHierarchyRecursively(data, parentId = 0) {
  const result = [];
  for (const item of data) {
      //判断是否找到了当前 parentId 下的子节点
    if (item.father_id === parentId) {
      const newItem = { ...item, _child: convertToHierarchyRecursively(data, item.id) };
        //将构建好的 newItem 对象添加到 result 数组中,表示成功找到并处理了当前 parentId 下的子节点
      result.push(newItem);
    }
  }
  return result;
}

// 使用示例
const hierarchyData = convertToHierarchyRecursively(arr);
console.log(JSON.stringify(hierarchyData, null, 2));

方法3:递归2

缺点:不灵活

function convertToHierarchy(flatArray, parentId) {
  let hierarchy = [];
  for (let item of flatArray) {
    if (item.father_id === parentId) {
      let newItem = {
        id: item.id,
        parentId: item.father_id,
        isEnabled: item.status === 1,
        name: item.name
      };
      let children = convertToHierarchy(flatArray, item.id);
      if (children.length > 0) {
        newItem._child = children;
      }
      hierarchy.push(newItem);
    }
  }
  return hierarchy;
}

let hierarchicalData = convertToHierarchy(flatData, 0);
console.log(JSON.stringify(hierarchicalData, null, 4));

 方法4:reduce

function convertToHierarchyWithReduce(arr) {
    //item当前对象  result处理后的每次循环对象
  return arr.reduce((result, item) => {
    const newItem = { ...item, _child: [] };
      //在 result 数组中查找是否存在 father_id 等于当前 item 的 id 的父节点。
    const parent = result.find(parentItem => parentItem.id === item.father_id);
    if (parent) {
      parent._child.push(newItem);
    } else {
      result.push(newItem);
    }
    return result;
  }, []);
}

// 使用示例
const hierarchyData = convertToHierarchyWithReduce(arr);
console.log(JSON.stringify(hierarchyData, null, 2));

三、借助上方思想用vue实现层级菜单

如下图

递归组件

递归组件是指在组件内部调用自身的一种组件设计模式。使用递归组件可以根据数据结构去动态渲染嵌套内容,例如树形结构、评论系统等。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值