ElementUi实现侧边栏动态生成(可无限层级展开)

后端返回的数据格式


 [
            {
                icon: "el-icon-s-home",
                id: "3964aacd-df2b-4172-89eb-6e4af50cd216",
                name: "测试1-1",
                pid: "8f51c44d-994d-4697-930c-c5539a9515f5",
                url: "/testOne-one"
            },
            {
                icon: "el-icon-s-data\r\n",
                id: "8f51c44d-456a-8asa-153a-83d563fce6b9",
                name: "测试2-1",
                pid: "d3217b03-48cb-40a8-89bd-83d563fce6b9",
                url: "/testTwo-two"
            },
            {
                icon: "el-icon-user-solid\r\n",
                id: "8f51c44d-994d-4697-930c-c5539a9515f5",
                name: "测试1",
                pid: "null",
                url: "/testOne"
            },
            {
                icon: "el-icon-star-on",
                id: "d3217b03-48cb-40a8-89bd-83d563fce6b9",
                name: "测试2",
                pid: "null",
                url: "/testTwo"
            },
            {
                icon: "el-icon-s-marketing\r",
                id: "d3217b03-as5a-12ad-89bd-6e4af50cd216",
                name: "测试1-1-1",
                pid: "3964aacd-df2b-4172-89eb-6e4af50cd216",
                url: "/testOne-one-one"
            }
        ]

转成el-menu需要的格式


[
    {
        "icon": "el-icon-user-solid\r\n",
        "id": "8f51c44d-994d-4697-930c-c5539a9515f5",
        "pid": "null",
        "name": "测试1",
        "url": "/testOne",
        "children": [
            {
                "icon": "el-icon-s-home",
                "id": "3964aacd-df2b-4172-89eb-6e4af50cd216",
                "pid": "8f51c44d-994d-4697-930c-c5539a9515f5",
                "name": "测试1-1",
                "url": "/testOne-one",
                "children": [
                    {
                        "icon": "el-icon-s-marketing\r",
                        "id": "d3217b03-as5a-12ad-89bd-6e4af50cd216",
                        "pid": "3964aacd-df2b-4172-89eb-6e4af50cd216",
                        "name": "测试1-1-1",
                        "url": "/testOne-one-one"
                    }
                ]
            }
        ]
    },
    {
        "icon": "el-icon-star-on",
        "id": "d3217b03-48cb-40a8-89bd-83d563fce6b9",
        "pid": "null",
        "name": "测试2",
        "url": "/testTwo",
        "children": [
            {
                "icon": "el-icon-s-data\r\n",
                "id": "8f51c44d-456a-8asa-153a-83d563fce6b9",
                "pid": "d3217b03-48cb-40a8-89bd-83d563fce6b9",
                "name": "测试2-1",
                "url": "/testTwo-two"
            }
        ]
    }
]

自定义封装方法 utils ---> arrayToTree.ts


// 数组转树结构
function sortArr(a: any, b: any) {
  return a.orderNum - b.orderNum;
}

export function arrayToTree(list: object[], callback: any = () => {}, props = { id: 'id', pid: 'pid', children: 'children' }) {
  list.sort(sortArr);
  const tree: object[] = [];
  const map: any = {};

  // list = cloneObj(list);

  const listLength = list.length;
  for (let i = 0; i < listLength; i++) {
    const node: any = list[i];
    const nodeId: any = node[props.id];
    map[nodeId] = node;
    callback(node);
  }

  for (let i = 0; i < listLength; i++) {
    const node: any = list[i];
    const nodePid: any = node[props.pid];
    const parentNode: any = map[nodePid];
    if (parentNode) {
      parentNode[props.children] = parentNode[props.children] || [];
      parentNode[props.children].push(node);
    } else {
      tree.push(node);
    }
  }

  return tree;
}

封装侧边栏组件 sideBar.vue


<template>
    <div>
        <template v-for="(item) in menuList">
            <!-- 有次级菜单的,则展开子选项-->
            <el-submenu v-if="item.children && item.children.length>0" :key="item.id" :index="item.id">
                <template #title>
                    <i v-if="item.icon" :class="item.icon"></i>
                    <span>{{item.name}}</span>
                </template>
                <!-- 递归,实现无限级展开 -->
                <side-bar :menuList="item.children"></side-bar>
            </el-submenu>
            <!-- 没有次级菜单的 -->
            <el-menu-item v-if="!item.children" :key="item.id" :index="item.url">
                <i v-if="item.icon" :class="item.icon"></i>
                <span>{{item.name}}</span>
            </el-menu-item>
        </template>
    </div>
</template>

<script lang="ts">
    import {Component, Prop, Vue} from 'vue-property-decorator';

    @Component({
        components: {},
    })
    export default class SideBar extends Vue {
        @Prop() menuList: any;

        created() {
        }
    }
</script>

<style lang="scss">
    
</style>

需要的地方使用sideBar.vue


<template>
    <div class="home">
        <el-menu class="el-menu"
                 background-color="#32323a"
                 :unique-opened="true"
                 :default-active="$route.path"
                 text-color="#ffffff"
                 router>
            <sideBar :menuList="menuList"/>
        </el-menu>
    </div>
</template>

<script lang="ts">
    import {Component, Prop, Vue} from 'vue-property-decorator';
    import sideBar from "@/components/sideBar.vue";
    import {getList} from "@/api/routerList";
    import {arrayToTree} from "@/utils/arrayToTree";

    @Component({
        components: {sideBar},
    })
    export default class Home extends Vue {
        private menuList: any = [];

        /**
         * 获取路由列表
         */
        getList() {
            getList().then((res: any) => {
                if (res.status === 200 && res.data.status === 200) {
                    this.menuList = arrayToTree(res.data.data)
                    console.log(this.menuList)
                }
            }).catch((error: any) => {
                throw(error);
            })
        }

        created() {
            this.getList();
        }
    }
</script>

<style lang="scss" scoped>

</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值