有关若依菜单管理的改造

时间:2024-10-03 07:37:34

导言:

  搞了个后端对接若依前端,对接菜单管理时候懵懵的就搞完了,也是搞了很久。记一下逻辑和要注意的东西,以后做想似的能有个改造思路。

逻辑:

主要是要把后端传过的数组列表做成类似

这样的,所以要转格式

后端传过来的数据:

const data = [
  { id: 1, name: '根节点1', parentId: null },
  { id: 2, name: '根节点2', parentId: null },
  { id: 3, name: '子节点1-1', parentId: 1 },
  { id: 4, name: '子节点1-2', parentId: 1 },
  { id: 5, name: '子节点2-1', parentId: 2 },
  { id: 6, name: '子节点1-1-1', parentId: 3 },
  { id: 7, name: '子节点1-1-2', parentId: 3 }
];

转换成el-table要的

const tree = [
  {
    id: 1,
    name: '根节点1',
    parentId: null,
    children: [
      {
        id: 3,
        name: '子节点1-1',
        parentId: 1,
        children: [
          { id: 6, name: '子节点1-1-1', parentId: 3 },
          { id: 7, name: '子节点1-1-2', parentId: 3 }
        ]
      },
      { id: 4, name: '子节点1-2', parentId: 1 }
    ]
  },
  {
    id: 2,
    name: '根节点2',
    parentId: null,
    children: [
      { id: 5, name: '子节点2-1', parentId: 2 }
    ]
  }
];

若依是定义了一个方法来实现转换的过程,大致思路:

  • 第一次循环用于建立节点之间的父子关系映射。
  • 第二次循环用于识别根节点并初始化树的结构。
  • 第三次循环则利用递归构建完整的树形结构,确保所有节点的层级关系正确。

讲实话我还是懵懵的,模糊理解

1.把扁平数组每个数据看成点,两点之间连线

2.分别把两点连线是父节点的一端找到

3.对应接起来

没什么实感..

实现

1.index.vue

请求后端,获得数据,调用handleTree转换格式,绑到表格上

/** 查询菜单列表 */
    getList() {
      this.loading = true;
      listMenu(this.queryParams).then(response => {
        console.log("请求信息response:",response);
        
        this.menuList = this.handleTree(response.data, "id","parentUID");
        console.log("请求信息this.menuList:",this.menuList);
        this.loading = false;
      });
    },

2.handleTree()转换

在src\utils\ruoyi.js里.

把扁平化的数组数据结构(通常是包含父子关系的节点)转换为一个树形结构

/**
 * 构造树型结构数据
 * @param {*} data 数据源           // 输入的原始数据,是一个扁平结构的数组
 * @param {*} id id字段 默认 'id'   // 数据中表示唯一标识符的字段名,默认为 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'  // 数据中表示父节点的字段名,默认为 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'  // 用来存储子节点的字段名,默认为 'children'
 */
export function handleTree(data, id = 'id', parentId = 'parentId', children = 'children') {
  
  // 配置对象,定义了 id 字段、parentId 字段、children 字段的名称
  let config = {
    id: id || 'id',                      // id 标识字段,默认为 'id'  
    parentId: parentId || 'parentId',     // 父节点标识字段,默认为 'parentId'
    childrenList: children || 'children'  // 子节点列表字段,默认为 'children'
  };

  // 存储每个父节点对应的子节点数组
  var childrenListMap = {}; 
  
  // 存储所有节点的 id 及其节点对象,用于快速查找
  var nodeIds = {};  
  
  // 最终的树形结构数组,存储根节点
  var tree = [];

  // 第一次循环:构建 childrenListMap 和 nodeIds
  for (let d of data) {
    let parentId = d[config.parentId];    // 获取当前节点的父节点 id

    if (childrenListMap[parentId] == null) {
      childrenListMap[parentId] = [];     // 如果该父节点还没有子节点数组,则初始化
    }
    
    nodeIds[d[config.id]] = d;            // 保存当前节点的 id 和节点本身,方便快速查找
    childrenListMap[parentId].push(d);     // 将当前节点加入到其父节点对应的子节点数组中

  }

  
  // 第二次循环:找出根节点,并添加到 tree 数组中
  for (let d of data) {
    let parentId = d[config.parentId];     // 获取当前节点的父节点 id

    if (nodeIds[parentId] == null ) {       // 如果当前节点的父节点不存在,说明它是根节点
      tree.push(d);                        // 将根节点加入到树结构中

    }
  }
  // 第三次循环:递归遍历根节点的子节点,并构造完整的树形结构
  for (let t of tree) {
    
    adaptToChildrenList(t);                // 递归处理每个根节点,生成其子节点结构
  }

  /**
   * 递归地将子节点添加到对应的父节点中
   * @param {*} o 当前正在处理的节点对象
   */
  function adaptToChildrenList(o) {
    if (childrenListMap[o[config.id]] !== null) {
      o[config.childrenList] = childrenListMap[o[config.id]];   // 将子节点数组添加到当前节点的 children 字段
    }
   
    if (o[config.childrenList]) {                               // 如果当前节点有子节点
      for (let c of o[config.childrenList]) {
        adaptToChildrenList(c);                                 // 递归处理每个子节点
      }
    }
  }

  // 返回最终构造好的树形结构
  return tree;
}

注意的点

1.handleTree()

这方法开始定义了config对象,其中把每个字段的父节点id,子节点的名字都规范好了,如果后端这俩传来的不一样的话在调用handleTree()时对应传过去就行,不然不一样用了默认的话会报错。

2.后端数据

后端传过来的每条数据都应该带上parentId字段,不管有没有,不然也会报错

3.el-table绑定

绑定的是本身的id,不是父节点的,绑父节点的会报键重复

<el-table
      v-if="refreshTable"
      v-loading="loading"
      :data="menuList"
      row-key="id"
      :default-expand-all="isExpandAll"
      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
    >