目录

  • 一、介绍
  • 二、目标
  • 三、代码
  • 四、完成



一、介绍

我们的国家国土面积十分的广阔,目前中国有 34 个省级行政区,包括 23 个省、5 个自治区、4 个直辖市、2 个特别行政区。其下面还有几千个县级区域,以及更多的乡镇区域。

这样层层嵌套的省市区数据在实际开发中是如何处理的呢?下面请运用所学,解开这个谜团吧~

二、目标

在实际开发中,由于省市区等层级较多,使得数据结构按照嵌套关系来存储则过于复杂,一般在数据库中会将省市区数据解耦,每条信息以并列关系存储在一张表中,结构如下:

[
  {
    id: "51", // 区域 id
    name: "四川省", // 区域名字
    pid: "0", // 区域的父级区域 id
  },
  {
    id: "5101",
    name: "成都市",
    pid: "51", // 成都的父级是四川省,所以 pid 是 51
  },
  // ...
];

各级行政区域通过 pid 关联起来。

但是这样平铺的数据放在前端页面展示的话,用户很难看出其中的层级关系,所以需要将平铺的结构转化为树状结构,便于前端展示:

[
  {
    id: "51", // 地址 id
    name: "四川省", // 地址名
    pid: "0", // 该地址的父节点 id
    children: [
      {
        id: "5101",
        name: "成都市",
        pid: "51",
        children: [
          {
            id: "510101",
            name: "市辖区",
            pid: "5101",
            children: [], // 如果该区域节点没有子集,children 则为空数组!!!
          },
          // ...
        ],
      },
      // ...
    ],
  },
  // ...
];

补充文件 convert-to-tree.js 中的 convertToTree 工具函数,使其实现我们需要的功能:

全国省市多选 jQuery_开发语言

  • 接收平铺的区域信息数组,并将其转化为树状结构,最终数据结构如上面介绍中所示(树状结构,且对于没有子集的叶子节点,其 children 属性设置为空数组)。
  • 并且还接收一个 rootId,用于标识返回哪一个区域下面的所有节点。默认为 0 表示返回所有省份信息(在我们的示例数据中,所有省份的 pid 都为 0)。

完成图:

全国省市多选 jQuery_数组_02

三、代码

html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>平铺数据生成树状结构</title>
  </head>
  <style>
    #output-container {
      width: 600px;
    }
  </style>
  <body>
    <div id="output-container"></div>
    <script>
      module = {};
    </script>
    <script type="text/javascript" src="./convert-to-tree.js"></script>
    <script>
      const convertToTreeFn = module.exports;
      const output = document.getElementById("output-container");

      const regions = [
        {
          id: "51",
          name: "四川省",
          pid: "0",
        },
        {
          id: "5101",
          name: "成都市",
          pid: "51",
        },
        {
          id: "5103",
          name: "自贡市",
          pid: "51",
        },
        {
          id: "5104",
          name: "攀枝花市",
          pid: "51",
        },
        {
          id: "5105",
          name: "泸州市",
          pid: "51",
        },
        
        {
          id: "5107",
          name: "绵阳市",
          pid: "51",
        },
        {
          id: "510101",
          name: "市辖区",
          pid: "5101",
        },
        {
          id: "510104",
          name: "锦江区",
          pid: "5101",
        },
        {
          id: "510105",
          name: "青羊区",
          pid: "5101",
        },
        {
          id: "510106",
          name: "金牛区",
          pid: "5101",
        },
        {
          id: "510107",
          name: "武侯区",
          pid: "5101",
        },
        {
          id: "510108",
          name: "成华区",
          pid: "5101",
        },
        {
          id: "510112",
          name: "龙泉驿区",
          pid: "5101",
        },
        {
          id: "510113",
          name: "青白江区",
          pid: "5101",
        },
        {
          id: "510114",
          name: "新都区",
          pid: "5101",
        },
        {
          id: "510115",
          name: "温江区",
          pid: "5101",
        },
        {
          id: "510116",
          name: "双流区",
          pid: "5101",
        },
        {
          id: "510117",
          name: "郫都区",
          pid: "5101",
        },
        {
          id: "510118",
          name: "新津区",
          pid: "5101",
        },
        {
          id: "510121",
          name: "金堂县",
          pid: "5101",
        },
        {
          id: "510129",
          name: "大邑县",
          pid: "5101",
        },
        {
          id: "510131",
          name: "蒲江县",
          pid: "5101",
        },
        {
          id: "510181",
          name: "都江堰市",
          pid: "5101",
        },
        {
          id: "510182",
          name: "彭州市",
          pid: "5101",
        },
        {
          id: "510183",
          name: "邛崃市",
          pid: "5101",
        },
        {
          id: "510184",
          name: "崇州市",
          pid: "5101",
        },
        {
          id: "510185",
          name: "简阳市",
          pid: "5101",
        },
        {
          id: "510301",
          name: "市辖区",
          pid: "5103",
        },
        {
          id: "510302",
          name: "自流井区",
          pid: "5103",
        },
        {
          id: "510303",
          name: "贡井区",
          pid: "5103",
        },
        {
          id: "510304",
          name: "大安区",
          pid: "5103",
        },
        {
          id: "510311",
          name: "沿滩区",
          pid: "5103",
        },
        {
          id: "510321",
          name: "荣县",
          pid: "5103",
        },
        {
          id: "510322",
          name: "富顺县",
          pid: "5103",
        },
        {
          id: "510401",
          name: "市辖区",
          pid: "5104",
        },
        {
          id: "510402",
          name: "东区",
          pid: "5104",
        },
        {
          id: "510403",
          name: "西区",
          pid: "5104",
        },
        {
          id: "510411",
          name: "仁和区",
          pid: "5104",
        },
        {
          id: "510421",
          name: "米易县",
          pid: "5104",
        },
        {
          id: "510422",
          name: "盐边县",
          pid: "5104",
        },
        {
          id: "510501",
          name: "市辖区",
          pid: "5105",
        },
        {
          id: "510502",
          name: "江阳区",
          pid: "5105",
        },
        {
          id: "510503",
          name: "纳溪区",
          pid: "5105",
        },
        {
          id: "510504",
          name: "龙马潭区",
          pid: "5105",
        },
        {
          id: "510521",
          name: "泸县",
          pid: "5105",
        },
        {
          id: "510522",
          name: "合江县",
          pid: "5105",
        },
        {
          id: "510524",
          name: "叙永县",
          pid: "5105",
        },
        {
          id: "510525",
          name: "古蔺县",
          pid: "5105",
        },
        {
          id: "510701",
          name: "市辖区",
          pid: "5107",
        },
        {
          id: "510703",
          name: "涪城区",
          pid: "5107",
        },
        {
          id: "510704",
          name: "游仙区",
          pid: "5107",
        },
        {
          id: "510705",
          name: "安州区",
          pid: "5107",
        },
        {
          id: "510722",
          name: "三台县",
          pid: "5107",
        },
        {
          id: "510723",
          name: "盐亭县",
          pid: "5107",
        },
        {
          id: "510725",
          name: "梓潼县",
          pid: "5107",
        },
        {
          id: "510726",
          name: "北川羌族自治县",
          pid: "5107",
        },
        {
          id: "510727",
          name: "平武县",
          pid: "5107",
        },
        {
          id: "510781",
          name: "江油市",
          pid: "5107",
        },
      ];
      const result = convertToTreeFn(regions);


      output.appendChild(getRegionDoms(result));

      function getRegionDoms(regions) {
        if (!regions || regions.length === 0) {
          return;
        }

        const ul = document.createElement("ul");
        regions.forEach((region) => {
          const li = document.createElement("li");
          const textNode = document.createTextNode(region.name);
          li.appendChild(textNode);
          const children = getRegionDoms(region.children);
          if (children) {
            li.appendChild(children);
          }
          ul.appendChild(li);
        });
        return ul;
      }
    </script>
  </body>
</html>

js

function convertToTree(regions, rootId = "0") {
  // TODO: 在这里写入具体的实现逻辑
  // 将平铺的结构转化为树状结构,并将 rootId 下的所有子节点数组返回
  // 如果不存在 rootId 下的子节点,则返回一个空数组
}

module.exports = convertToTree; // 检测需要,请勿删除

四、完成

function convertToTree(regions, rootId = "0") {
  // TODO: 在这里写入具体的实现逻辑
  // 将平铺的结构转化为树状结构,并将 rootId 下的所有子节点数组返回
  // 如果不存在 rootId 下的子节点,则返回一个空数组
  let newArr = []
  //先遍历regions 如果pid和rootId相等那么将其加入newArr
  regions.forEach(item => {
    //如果存在pid和rootId相同
    if (item.pid == rootId) {
      newArr.push(item)
      //递归调用 将id作为下一个rootId与pid相比
      item.children = convertToTree(regions, item.id)
    }
  })
  return newArr
}

module.exports = convertToTree; // 检测需要,请勿删除