zoukankan      html  css  js  c++  java
  • 树形多级菜单数据源嵌套结构与扁平结构互转

    树形多级菜单数据源嵌套结构与扁平结构互转

    数据源格式

    一般来说,要想动态渲染树形菜单,这个样子的数据源格式对前端很友好。

    var data = [
    	{
        name: "父节点1",
        children: [
          {
            name: "子节点11",
            children:[
              {
                name: "叶子节点111",
                children:[]
              },
              {
                name: "叶子节点112",
                children:[]
              },
              {
                name: "叶子节点113",
                children:[]
              },
              {
                name: "叶子节点114",
                children:[]
              }
            ]
          }
         //...
        ]
      },
    ];
    

    问题

    在后端,这些数据通常是存储在关系型数据库中,后端开发将数据从数据库中取出来返回给前端的数据往往这样子的:

    const data =[
      { id:1,   pid:0,  name:"父节点1"     },           
      { id:11,  pid:1,  name:"父节点11"    },
      { id:111, pid:11, name:"叶子节点111" },
      { id:112, pid:11, name:"叶子节点112" },
      { id:113, pid:11, name:"叶子节点113" },
      { id:114, pid:11, name:"叶子节点114" },
      { id:12,  pid:1,  name:"父节点12"    },
      { id:121, pid:12, name:"叶子节点121" },
      { id:122, pid:12, name:"叶子节点122" },
      { id:123, pid:12, name:"叶子节点123" },
      { id:124, pid:12, name:"叶子节点124" },
      { id:13,  pid:1,  name:"父节点13"    },
      { id:2,   pid:0,  name:"父节点2"     },
      { id:21,  pid:2,  name:"父节点21"    },
      { id:211, pid:21, name:"叶子节点211" },
      { id:212, pid:21, name:"叶子节点212" },
      { id:213, pid:21, name:"叶子节点213" },
      { id:214, pid:21, name:"叶子节点214" },
      { id:22,  pid:2,  name:"父节点22"    },
      { id:221, pid:22, name:"叶子节点221" },
      { id:222, pid:22, name:"叶子节点222" },
      { id:223, pid:22, name:"叶子节点223" },
      { id:224, pid:22, name:"叶子节点224" },
      { id:23,  pid:2,  name:"父节点23"    },
      { id:231, pid:23, name:"叶子节点231" },
      { id:232, pid:23, name:"叶子节点232" },
      { id:233, pid:23, name:"叶子节点233" },
      { id:234, pid:23, name:"叶子节点234" },
      { id:3,   pid:0,  name:"父节点3"     }
    ];
    

    解决方案

    扁平转嵌套

    /**
     * 将一个普通的节点数组(带有指向父节点的指针)转换为嵌套的数据结构。
     * @param {*} data  一组数据
     * @param {*} option 包含以下字段的对象:
     *      parentProperty(String):可以找到父节点链接的属性的名称。默认值:'pid'。
     *      childrenProperty(String):将存储子节点的属性的名称。默认值:'children'。
     *      idProperty(String):唯一的节点标识符。默认值:'id'。
     *      nameProperty(String):节点的名称。默认值:'name'。
     */
    function FlatToNested(data, option) {
      option = option || {};
      let idProperty = option.idProperty || 'id';
      let parentProperty = option.parentProperty || 'pid';
      let childrenProperty = option.childrenProperty || 'children';
      let res = [],
        tmpMap = [];
      for (let i = 0; i < data.length; i++) {
        tmpMap[data[i][idProperty]] = data[i];
        if (tmpMap[data[i][parentProperty]] && data[i][idProperty] != data[i][parentProperty]) {
          if (!tmpMap[data[i][parentProperty]][childrenProperty])
            tmpMap[data[i][parentProperty]][childrenProperty] = [];
          tmpMap[data[i][parentProperty]][childrenProperty].push(data[i]);
        } else {
          res.push(data[i]);
        }
      }
      return res;
    }
    

    如果返回的数据和示例数据的字段不一致,那么您也无需更改源代码,方法提供了可配置选项,如下所示:

    例如,您收到这样的数据:

    const data =[
        { _id:1,   parentID:0,  text:"父节点1"     },           
        { _id:11,  parentID:1,  text:"父节点11"    },
        { _id:111, parentID:11, text:"叶子节点111" },
        { _id:112, parentID:11, text:"叶子节点112" },
        { _id:113, parentID:11, text:"叶子节点113" },
        { _id:114, parentID:11, text:"叶子节点114" },
        { _id:12,  parentID:1,  text:"父节点12"    },
        { _id:121, parentID:12, text:"叶子节点121" },
        { _id:122, parentID:12, text:"叶子节点122" }
        //...
      ];
    

    那么,您可以这样调用函数:

    FlatToNested(nodes,{
        idProperty:'_id',            //唯一的节点标识符。
        nameProperty:'text',         //节点的名称。
        parentProperty:'parentID',  //可以找到父节点链接的属性的名称。
        childrenProperty:'son'      //将存储子节点的属性的名称。
    })
    
    ### 嵌套转扁平
    
    ​```javascript
    /**
     * 嵌套型格式转扁平型格式
     * @param {Array} data 
     */
    function NestedToFlat(data,pid) { 
      var res = []
      for (var i = 0; i < data.length; i++) {
        res.push({
          id: data[i].id,
          name: data[i].name,
          pid: pid || 0
        })
        if (data[i].children) {
          res = res.concat(NestedToFlat(data[i].children, data[i].id));
        }
      }
      return res;
    }
    
  • 相关阅读:
    bzoj3160(FFT+回文自动机)
    bzoj2555(后缀自动机+LCT)
    luogu P4299 首都
    Annihilate(SA)
    [FJOI2016]神秘数(脑洞+可持久化)
    [ZJOI2016]大森林(LCT)
    bzoj3756pty的字符串(后缀自动机+计数)
    UVa 11582 Colossal Fibonacci Numbers! (斐波那契循环节 & 快速幂)
    UVa 12563 Jin Ge Jin Qu hao (0-1背包)
    UVa 437 The Tower of Babylon (DAG最长路)
  • 原文地址:https://www.cnblogs.com/ssaylo/p/14029273.html
Copyright © 2011-2022 走看看