js构造树形菜单

Posted WindEyes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js构造树形菜单相关的知识,希望对你有一定的参考价值。

先上个效果图

获取到的数据是这样的

[
    { id: 1, text: \'一级菜单A\', parentId: null },
    { id: 2, text: \'一级菜单B\', parentId: null },
    { id: 3, text: \'一级菜单C\', parentId: null },
    { id: 4, text: \'二级菜单AA\', parentId: 1 },
    { id: 5, text: \'二级菜单AB\', parentId: 1 },
    { id: 6, text: \'二级菜单AC\', parentId: 1 },
    { id: 7, text: \'二级菜单BA\', parentId: 2 },
    { id: 8, text: \'二级菜单BB\', parentId: 2 },
    { id: 9, text: \'二级菜单BC\', parentId: 2 },
    { id: 10, text: \'二级菜单CA\', parentId: 3 },
    { id: 11, text: \'二级菜单CB\', parentId: 3 },
    { id: 12, text: \'二级菜单CC\', parentId: 3 },
    { id: 13, text: \'三级菜单AAA\', parentId: 4 },
    { id: 14, text: \'三级菜单BAA\', parentId: 7 },
    { id: 15, text: \'三级菜单CAA\', parentId: 10 }
    ]

那如何将这些数据转化为树状结构并渲染出来

先上完整代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        ul,
        li {
            list-style: none;
        }
    </style>
</head>

<body>
    <div class="nav">

    </div>
</body>
<script>
    // 数据
    let navData = [
    { id: 1, text: \'一级菜单A\', parentId: null },
    { id: 2, text: \'一级菜单B\', parentId: null },
    { id: 3, text: \'一级菜单C\', parentId: null },
    { id: 4, text: \'二级菜单AA\', parentId: 1 },
    { id: 5, text: \'二级菜单AB\', parentId: 1 },
    { id: 6, text: \'二级菜单AC\', parentId: 1 },
    { id: 7, text: \'二级菜单BA\', parentId: 2 },
    { id: 8, text: \'二级菜单BB\', parentId: 2 },
    { id: 9, text: \'二级菜单BC\', parentId: 2 },
    { id: 10, text: \'二级菜单CA\', parentId: 3 },
    { id: 11, text: \'二级菜单CB\', parentId: 3 },
    { id: 12, text: \'二级菜单CC\', parentId: 3 },
    { id: 13, text: \'三级菜单AAA\', parentId: 4 },
    { id: 14, text: \'三级菜单BAA\', parentId: 7 },
    { id: 15, text: \'三级菜单CAA\', parentId: 10 }
    ];
    // let nav = document.getElementsByClassName(\'nav\')
    let nav = document.querySelector(\'.nav\')
    // 将数组置为树形
    let treeee = (function makeTreeData(arr, parentId) {
        let temp = []
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].parentId === parentId) {
                temp.push(arr[i])
                arr[i].children = makeTreeData(navData, arr[i].id)
            }
        }
        return temp
    })(navData, null)
    console.log(treeee);
    // 创造dom树
    (function makeDomTree(data, node) {
        let ul
        for (let i = 0; i < data.length; i++) {
            ul = document.createElement(\'ul\')
            let li = document.createElement(\'li\')
            li.innerHTML = data[i].text
            node.appendChild(ul)
            ul.appendChild(li)
            if (data[i].children.length !== 0) {
                let element = makeDomTree(data[i].children, ul)
                ul.appendChild(element)
            }

        }
        return ul
    })(treeee, nav)
</script>

</html>

分为两步

解析

第一步将数据进行转化

需要将数据转化为如下格式

      [
          { id: 1,
            text: \'一级菜单A\', 
            parentId: null ,
            children:[
                  { id: 4, text: \'二级菜单AA\', parentId: 1 ,children[{ id: 13, text: \'三级菜单AAA\', parentId: 4,children:[] }]},
                  { id: 5, text: \'二级菜单AB\', parentId: 1 ,children[]},
                  { id: 6, text: \'二级菜单AC\', parentId: 1 ,children[]}
            ]
            },
      ...
      ]

也就是说可以利用children属性让我们很清楚的看到,每个菜单的子菜单有多少项并包含着每项子菜单的每个属性
代码时这样子的,利用递归算法直接构建数据

 let treeee = (function makeTreeData(arr, parentId) {
        let temp = []
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].parentId === parentId) {
                temp.push(arr[i])
                arr[i].children = makeTreeData(navData, arr[i].id)
            }
        }
        return temp
    })(navData, null)
    console.log(treeee);

第二步将数据渲染至页面

let nav = document.querySelector(\'.nav\')
(function makeDomTree(data, node) {
        let ul //创建一个ul节点
        for (let i = 0; i < data.length; i++) {
            ul = document.createElement(\'ul\')
            let li = document.createElement(\'li\')
            li.innerHTML = data[i].text
            node.appendChild(ul)
            ul.appendChild(li)
            //以上几步是将当前数组的每个项都作为一个li放置到ul中
            //若有子项进行递归操作
            if (data[i].children.length !== 0) {
                let element = makeDomTree(data[i].children, ul)
                ul.appendChild(element)
            }

        }
        return ul //返回ul节点
    })(treeee, nav) //treeee是之前构建好的数据

以上是关于js构造树形菜单的主要内容,如果未能解决你的问题,请参考以下文章

jsTree树形菜单分类

html与js 如何实现树形菜单

EasyUI创建异步树形菜单和动态添加tab页面

JSP实现树形菜单

Vue.js怎样把递归组件构建为树形菜单

treeview-树形菜单js组件编写及应用