zoukankan      html  css  js  c++  java
  • 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) {
    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;
    230px;
    // position: absolute;
    // top: 0px;
    // bottom: 0px;
    .el-menu{
    height: 100%;
    background: #eef1f6;
    }
    .collapsed{
    64px;
    .item{
    position: relative;
    }
    .submenu{
    position:absolute;
    top:0px;
    left:64px;
    z-index:99999;
    height:auto;
    display:none;
    }
    }
    }
    .menu-collapsed{
    flex:0 0 64px;
    64px;
    }
    .menu-expanded{
    flex:0 0 230px;
    230px;
    }
    </style>
    利用次思想就可以形成一个简单的动态加载的例子

  • 相关阅读:
    【leetcode】Binary Search Tree Iterator
    【leetcode】Palindrome Partitioning II
    【leetcode】Best Time to Buy and Sell Stock III
    【leetcode】Best Time to Buy and Sell Stock II
    【leetcode】Longest Consecutive Sequence
    【leetcode】Factorial Trailing Zeroes
    【leetcode】Simplify Path
    【leetcode】Generate Parentheses
    【leetcode】Combination Sum II
    【leetcode】Combination Sum
  • 原文地址:https://www.cnblogs.com/orange2013/p/10520632.html
Copyright © 2011-2022 走看看