vue2.0后台管理 动态加载菜单【转载】

最近接手一个后台管理项目,需要实现从后台拉取导航菜单的效果;根据不同的登录用户的权限分别拉取不同的导航菜单,进行页面的跳转

实现方法:

从后台返回菜单与动态路由的数组做匹配,选择需要动态加载的路由,在将后台返回的菜单加载到页面即可

1.首先在本地固定配置好不变的路由的地址,例如登录,404,403,500等公用页面

const constantRouterMap = [
  {
    path:'/login',
    name:'Login',
    component:Login
  },
  {
    path: '/',
    name:'',
    component:layout,
    redirect: '/home',
    children:[
      { path:'/home',
        component:home,
        name:'首页页面',
        meta:{
          close:false
        }
      }
    ]
  },
  {
    path: "/500",
    name: "serverError",
    component: serverError
  },
  {
    path: "/403",
    name: "notPermission",
    component: notPermission
  },
  {
    path: "/404",
    name: "notFound",
    component: notFound
  },
  {
    path: "*", // 此处需特别注意置于最底部
    redirect: "/404"
  }
]

2.动态加载的菜单配置

//动态加载的路由
const asyncRouterMap = [
      {
        path:'/sys/user',
        component:sys_user,
        name:'用户权限',
        meta:{
          close:true
        }
      },
      {
        path:'/sys/sysPermission',
        component:sys_menu,
        name:'权限管理',
        meta:{
          close:true
        }
      },
      {
        path:'/sys/role',
        component:sys_role,
        name:'角色管理',
        meta:{
          close:true
        }
      },
      {
        path:'/sys/appMenu',
        component:sys_dept,
        name:'菜单管理',
        meta:{
          close:true
        }
      },
      {
        path:'/dict',
        component:dict,
        name:'字典管理',
        meta:{
          close:true
        }
      }
  ]
3.利用后台返回的菜单的格式
{"code":200,"msg":"success","data":[{"id":"2","isNewRecord":false,"createDate":"2013-05-27 08:00:00","updateDate":"2013-05-27 08:00:00","parentIds":"0,1,","name":"系统设置","sort":900,"isShow":"1","isApp":"0","children":[{"id":"44c896e862264fc883b7dbe35a56ea55","isNewRecord":false,"remarks":"","createDate":"2017-03-06 20:59:16","updateDate":"2017-11-29 14:51:12","parentIds":"0,1,2,","name":"组织机构","href":"","target":"","icon":"","sort":10,"isShow":"1","permission":"","isApp":"0","children":[{"id":"17","isNewRecord":false,"remarks":"","createDate":"2013-05-27 08:00:00","updateDate":"2017-03-06 21:00:01","parentIds":"0,1,2,44c896e862264fc883b7dbe35a56ea55,","name":"机构管理","href":"/sys/office","target":"","icon":"th-large","sort":40,"isShow":"1","permission":"","isApp":"0","children":[],"parentId":"44c896e862264fc883b7dbe35a56ea55"},{"id":"20","isNewRecord":false,"remarks":"","createDate":"2013-05-27 08:00:00","updateDate":"2017-03-06 21:00:29","parentIds":"0,1,2,44c896e862264fc883b7dbe35a56ea55,","name":"人员管理","href":"/sys/user","target":"","icon":"user","sort":50,"isShow":"1","permission":"","isApp":"0","children":[],"parentId":"44c896e862264fc883b7dbe35a56ea55"}],"parentId":"2"},{"id":"3","isNewRecord":false,"createDate":"2013-05-27 08:00:00","updateDate":"2013-05-27 08:00:00","parentIds":"0,1,2,","name":"系统设置","sort":20,"isShow":"1","isApp":"0","children":[{"id":"4","isNewRecord":false,"remarks":"","createDate":"2013-05-27 08:00:00","updateDate":"2017-12-18 11:09:05","parentIds":"0,1,2,3,","name":"PC菜单管理","href":"/sys/webMenu","target":"","icon":"list-ul","sort":30,"isShow":"1","permission":"","isApp":"0","children":[],"parentId":"3"},{"id":"8f0210e672a54b0282d08ce3a9259c66","isNewRecord":false,"remarks":"","createDate":"2017-12-18 10:28:22","updateDate":"2017-12-18 11:09:55","parentIds":"0,1,2,3,","name":"APP菜单管理","href":"/sys/appMenu","target":"","icon":"list","sort":40,"isShow":"1","permission":"","isApp":"0","children":[],"parentId":"3"},{"id":"7","isNewRecord":false,"remarks":"","createDate":"2013-05-27 08:00:00","updateDate":"2017-11-30 13:38:50","parentIds":"0,1,2,3,","name":"角色管理","href":"/sys/role","target":"","icon":"group","sort":50,"isShow":"1","permission":"","isApp":"0","children":[],"parentId":"3"}],"parentId":"2"}],"parentId":"1"}]}
4.通过一个函数将菜单与动态的路由做匹配
export function filterAsyncRouter(asyncRouterMap=[],menuTree=[]){
  const res = []
  const routers = getRoute(menuTree)
  asyncRouterMap.forEach((route)=>{
    var routeItem = route
    routers.forEach((item)=>{
      if(item.href==routeItem.path){
        //将后台返回的name赋值给前台定义好的
        routeItem.name = item.name
        res.push(routeItem)
      }
    })
  })
  return res;
}

5.利用路由的addRouter的特性将于菜单匹配到的路由加载到路由中

  let asyncRouterMaps = filterAsyncRouter(asyncRouterMap,store.state.navTree)

asyncRouterMaps.forEach((route)=>{
  router.options.routes[1].children.push(route)
})
router.addRoutes(router.options.routes)

6.再将后台返回的菜单加载到页面中即可:
menuTree.vue加载一个菜单的component

<template>
  <el-submenu v-if="menu.children && menu.children.length >= 1" :index="'' + menu.id">
    <template slot="title">
      <i :class="menu.icon" ></i>
      <span slot="title">{{menu.name}}</span>
    </template>
    <MenuTree v-for="item in menu.children" :key="item.id" :menu="item"></MenuTree>
  </el-submenu>
  <el-menu-item v-else :index="(menu.href?menu.href:menu.id)">
    <i :class="menu.icon"></i>
    <span slot="title">{{menu.name}}</span>
  </el-menu-item>
</template>
在home的navbar中引用到需要的地方即可
<template>
  <!--导航栏部分-->
  <aside :class="collapsed?'menu-collapsed':'menu-expanded'">
    <el-menu ref="navmenu" :default-active="$router.history.current.path" router unique-opened class="el-menu-vertical-demo" @select="handleSelect" @open="handleOpen" @close="handleClose" :collapse="collapsed">
      <menu-tree v-for="item in navTree" :key="item.id" :menu="item"></menu-tree>
    </el-menu>
  </aside>
</template>

<style>
  .el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 230px;
  }
</style>

<script>
  import store from '@/store'
  import router from '@/router'
  import {mapState} from 'vuex'
  import MenuTree from '@/components/menuTree'
  import { setTab,getTab } from '@/utils/auth'
  export default {
    data() {
      return {
        navTree:this.$store.state.navTree,
      };
    },
    components:{
      MenuTree
    },
    watch:{
      '$route':'handleRoute'
    },
    created () {
      this.handleRoute(this.$route)
    },
    methods: {
      handleOpen(key, keyPath) {
      },
      handleClose(key, keyPath) {
      },
      handleSelect(key,keyPath){
      },
      handleRoute(route){
        //标签页选中,如果不存在则先添加
        //检查现有的tab标签中是否存在,通过path去判断
        var tab = this.mainTabs.filter(item => item.name === route.name)[0]
        if(!tab){
          tab = {
            name:route.name,
            title:route.name,
            path:route.path,
            close:route.meta.close
          }
          this.mainTabs = this.mainTabs.concat(tab)
        }
        setTab(this.mainTabs)
        this.mainTabsActiveName = route.name
        // 切换标签页时同步更新高亮菜单
        if(this.$refs.navmenu != null) {
          this.$refs.navmenu.activeIndex = route.path
          this.$refs.navmenu.initOpenedMenu()
        }
      }
    },
    computed:{
      ...mapState({
          collapsed:'collapse',
        }),
      mainTabs:{
        get () { return this.$store.state.mainTabs },
        set (val) { this.$store.commit('getMainTabs', val) }
      },
      mainTabsActiveName: {
        get () { return this.$store.state.mainTabsActiveName },
        set (val) { this.$store.commit('getMainTabsActiveName', val) }
      }
    },
    mounted(){

    }
  }
</script>

<style lang="less" scoped>mainTabs
  aside {
    flex:0 0 230px;
    width: 230px;
    // position: absolute;
    // top: 0px;
    // bottom: 0px;
    .el-menu{
      height: 100%;
      background: #eef1f6;
    }
    .collapsed{
      width:64px;
      .item{
        position: relative;
      }
      .submenu{
        position:absolute;
        top:0px;
        left:64px;
        z-index:99999;
        height:auto;
        display:none;
      }
    }
  }
  .menu-collapsed{
    flex:0 0 64px;
    width: 64px;
  }
  .menu-expanded{
    flex:0 0 230px;
    width: 230px;
  }
</style>
利用次思想就可以形成一个简单的动态加载的例子

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值