递归封装menu

41 阅读1分钟

封装侧边栏菜单 element ui vue2

在引用的时候 直接 使用即可

页面使用 collapse 可收缩 unique-opened 只打开一个

<template>
  <el-scrollbar view-style="font-weight: bold;" style=" position: relative" :native="false">
    <el-menu :default-active="$route.path" class="el-menu-vertical-demo" :collapse="isCollapse" background-color="#545c64"
      text-color="#fff" active-text-color="#ffd04b" unique-opened router>
      <h3>{{ isCollapse ? '后台' : '后台管理系统' }}</h3>
      <Menu :dataList="menuData"></Menu>
    </el-menu>
  </el-scrollbar>
</template>

<script>
import Menu from './menuItem.vue'
import Cookies from 'js-cookie'
import { mapState } from 'vuex'
export default {
  name: "NavItem", //组件的名称
  data() {
    return {
      // isCollapse:false,
      navListDatas: [
        {

          "path": "/home",
          "title": "首页",
          "icon": "s-fold",
          "id": 1
        },
        {
          "title": "用户管理",
          "icon": "s-fold",
          "path": "/user",
          "id": 2
        },
        {
          "title": "引导页",
          "icon": "s-fold",
          "path": "/guide",
          "id": 3
        },
        {
          "title": "权限测试页",
          "icon": "s-fold",
          "id": 4,
          "children": [
            {
              "title": "页面权限",
              "icon": "s-fold",
              "id": "4-1",
              children: [
                {
                  title: "菜单1-1-1",
                  icon: "el-icon-s-home",
                  path: "/role/roleone"
                },
                {
                  title: "菜单1-1-2",
                  icon: "el-icon-s-home",
                  path: "/role/roletwo"
                }
              ]
            },
            {
              "title": "指令权限",
              "icon": "Lock",
              "id": "4-2",
              children: [
                {
                  title: "菜单1-2-2-1",
                  icon: "el-icon-s-home",
                  path: "/menu221"
                },
                {
                  title: "菜单1-2-2-2",
                  icon: "el-icon-s-home",
                  path: "/menu222"
                }
              ]
            },
            {
              "title": "指令权限",
              "icon": "Lock",
              "path": "/limitrole",
              "id": "4-3"
            }
          ]
        },
        {
          "title": "图标",
          "icon": "Picture",
          "path": "/icon",
          "id": 5
        },
        {
          "title": "订单管理",
          "icon": "Money",
          "id": 6,
          "children": [
            {
              "title": "订单列表",
              "icon": "Money",
              "path": "/fromlist",
              "id": "6-1"
            },
            {
              "title": "添加订单",
              "icon": "Money",
              "path": "/addfromlist",
              "id": "6-2"
            }
          ]
        }
      ],
    }
  },
  components: {
    Menu
  },
  computed: {
    isCollapse() {
      return this.$store.state.tabs.isCollapse
    },
    menuData() {
      const menuCookie = Cookies.get('menu')
      if (!menuCookie) {
        return this.$store.state.tabs.menu
      }
      try {
        return JSON.parse(menuCookie)
      } catch (error) {
        return this.$store.state.tabs.menu
      }
      // return  JSON.parse(Cookies.get('menu')) || this.$store.state.tabs.meun
    }
  },
  methods: {
    clickItem(item) {
      if (this.$route.path !== item.index && !(this.$route.path === '/home' && (item.path === '/'))) {
        this.$router.push(item.index)
      }
    },
  },



}
</script>

<style scoped lang="scss">
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-width: 64px;
}

.el-menu {
  height: 100vh;
  border-right: none;

  h3 {
    color: #fff;
    text-align: center;
    line-height: 48px;
    font-size: 16px;
    font-weight: 400;
  }
}
</style>

以下是详情代码

<template>
    <div>
        <template v-for="(item) in dataList">
            <el-submenu :index="(item.path || item.id).toString()" v-if="item.children && item.children.length"
                :key="item.id">
                <template slot="title">
                    <i :class="`el-icon-${item.icon}`"></i>
                    <span>{{ item.title }}</span>
                </template>
                <Menu :dataList="item.children" ></Menu>
            </el-submenu>
            <template v-else>
                <!-- el-menu 添加 router 属性 使用 vue-router 的模式,在激活导航时以 index 作为 path 进行路由跳转 -->
                <el-menu-item :index="item.path" :key="item.name" @click="handleMenuItemClick(item)">
                    <i :class="`el-icon-${item.icon}`"></i>
                    <span slot="title">{{ item.title }}</span>
                </el-menu-item>
                <!-- <el-menu-item :index="item.path" :key="item.name" >
                    <i :class="`el-icon-${item.icon}`"></i>
                    <span slot="title">{{ item.title }}</span>
                </el-menu-item> -->
            </template>
        </template>
    </div>
</template>



<script>
export default {
    name: "Menu",
    data() {
        return {

        }
    },
    props: {
        dataList: {
            type: Array,
            required: true
        }
    },
    computed: {
    },
    mounted() {
    },
    methods: {
        handleMenuItemClick(item) {
            console.log('点击菜单', item);
            // 跳转页面
            if (this.$route.path !== item.path  && (this.$route.path == '/home' && (item.path =='/'))) {
                this.$router.push(item.path);
            }
            // 更新面包屑
            this.$store.commit('seleCrumbList',item)
        }
    }
}
</script>

<style lang="scss" scoped>
/*隐藏文字*/
.el-menu--collapse .el-submenu__title span {
    display: none;
}

/*隐藏 > */
.el-menu--collapse .el-submenu__title .el-submenu__icon-arrow {
    display: none;
}
</style>

可能会遇到一个问题,就是element-ui 中布局 左边侧边栏,宽度问题

style="width:auto" 需要给这个属性

<el-aside width="auto">
<!-- 左侧导航栏 -->
           <NavItem />
</el-aside>

第三个     Menu 组件

这里会有最严重的bug 收缩的时候 多级嵌套的文字不收起来 ,原因是 div 导致的

解决办法 有 1.css解决

<style lang="scss" scoped>
/*隐藏文字*/
.el-menu--collapse .el-submenu__title span {
    display: none;
}

/*隐藏 > */
.el-menu--collapse .el-submenu__title .el-submenu__icon-arrow {
    display: none;
}
</style>

  1. 利用插件

import Fragment from 'vue-fragment'

components: { Fragment },

把div 换成 <vue-fragment class="menu-list">vue-fragment >