实战实现后台管理系统菜单(vue递归组件)

1,751 阅读2分钟

概述

在日常工作中,递归是个人必会的技巧,如果是经常做后台管理系统的,可以经常看到左侧的菜单大差不差基本上都差不多,如果公司扩展不高的话,就手动每次配置一两层就行,但是如果碰到动态配置左侧菜单的情形,这时候必须要递归生成菜单,这样多少层级的菜单都能实现,提高了扩展性,这里主要介绍vue中递归组件的使用。

效果

gif演示,请稍等会儿

1112.gif

实现

前置知识

需要了解vue的递归组件,可以自行前往官网查看具体的解释,说白了就是组件的递归使用,和函数递归的思想是一样的。

代码实现

  • 自行初始化项目,我演示用的vue+cli
  • 下载组件库,这里element做演示
  • 新建Layout.vue组件
<template>
  <el-container>
    <el-header>Header</el-header>
    <el-container>
      <el-aside :width="isCollapse ? '64px' : '250px'">
        <el-menu
          default-active="1"
          class="el-menu-vertical-demo"
          @open="handleOpen"
          @close="handleClose"
          :collapse="isCollapse"
          popper-append-to-body
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#ffd04b"
        >
          <LayoutMenu :list="permissionTreeData"  :collapse="isCollapse"></LayoutMenu>
        </el-menu></el-aside
      >
      <el-main><router-view></router-view></el-main>
    </el-container>
  </el-container>
</template>

<script>
import { permissionTreeData } from "@/router/permissionTreeData";
import LayoutMenu from "./LayoutMenu.vue";
export default {
  components: { LayoutMenu },
  data() {
    return {
      isCollapse: false,
      permissionTreeData,
    };
  },
  methods: {
    toggleMenuShowStatus() {
      this.isCollapse = !this.isCollapse;
    },
  },
};
</script>

<style>
.el-container {
  height: 100vh;
  width: 100%;
}
.el-header {
  background-color: #000;
  color: #fff;
}
.el-aside {
  height: 100%;
  background-color: #545c64;
}
</style>

  • 准备好左侧菜单数据,为树形结构的数组
export const permissionTreeData = [
  {
    name: "design",
    label: "设计管理",
    id: "1",
    children: [
      {
        name: "design-detail",
        label: "设计管理详情",
        id: "1-1",
      },
    ],
  },
  {
    name: "I118Test",
    label: "国际化测试",
    id: "211",
  },
  {
    name: "plantForm",
    label: "平台表单管理",
    id: "3",
    children: [
      {
        name: "plantForm-list",
        label: "平台管理列表",
        id: "3-1",
      },
    ],
  },
  {
    name: "user",
    label: "用户管理",
    id: "211",
  },
  {
    name: "app",
    id: "4",
    label: "应用管理",
    children: [
      {
        name: "app-detail",
        id: "4-1",
        label: "应用详情",
        children: [
          {
            name: "app-detail-test",
            label: "应用详情测试",
            id: "4-2",
          },
          {
            name: "app-preview",
            label: "应用详情预览",
            id: "4-3",
            children: [
              {
                name: "plantForm-list",
                label: "应用详情编辑",
                id: "4-3-1",
              },
            ],
          },
          {
            name: "design-detail",
            label: "设计器详细信息",
            id: "4-4",
          },
        ],
      },
      {
        name: "app-detail",
        label: "应用详情",
        id: "5-1",
        children: [
          {
            name: "app-detail-test",
            label: "应用注册",
            id: "5-2",
          },
          {
            name: "I118Test",
            label: "应用部署",
            id: "5-3",
          },
          {
            name: "design-detail",
            label: "应用发布",
            id: "5-4",
          },
        ],
      },
    ],
  },
];

新建LayutMenu.vue组件

注意:name一定要给,递归组件的核心

<template>
  <div>
    <template v-for="item in list">
      <template v-if="item.children">
        <el-submenu :index="item.id">
          <template slot="title">
            <i class="el-icon-location"></i>
            <span :class="collapse ? 'collapse-title' : ''">{{
              item.label
            }}</span>
          </template>
          <LayoutMenu :list="item.children"></LayoutMenu>
        </el-submenu>
      </template>
      <template v-else>
        <el-menu-item :index="item.id">
          <i class="el-icon-location"></i>
          <span slot="title" @click="$router.push({ name: item.name })">{{
            item.label
          }}</span>
        </el-menu-item>
      </template>
    </template>
  </div>
</template>

<script>
export default {
//核心,name一定要给,递归组件的核心
  name: "LayoutMenu",
  props: {
    list: {
      type: Array,
      default: () => [],
    },
    collapse: {
      type: Boolean,
      default: false,
    },
  },
};
</script>

<style>
.collapse-title {
  opacity: 0;
}
</style>

总结

上面的菜单数据可以由后端返回,然后前台自行处理成对应权限的菜单数据列表,还可以基于此,实现动态路由权限的功能,总之就是映射,如果对函数递归理解到位的话,其实都还是很好处理的,上面是vue里面的实现,vue3类似的,区别不大。