vue+ element 后台动态生成权限菜单,前端动态绑定路由

导语

人生呀 总会有一些改变,入行快2年了,今天来记录下我的第一篇博客,哈哈 不管有没有人看。

开始正题

一、通过后端返回的信息 动态添加路由

首先登录,获取到你的用户信息,把token存在cookies 里面,然后跳转系统首页。在跳转之前我做了一个路由处理 新增了一个 permission.js 直接在main.js 引用就可以了
在这里插入图片描述
这个文件用了 router 的 beforeEach ,我是在每次路由请求之前 执行 GetUserInfo,GenerateRoutes 这两个方法,把用户信息和路由信息存到仓库里面。(这是为了防止刷新浏览器后动态添加的菜单不存在了。)

router.beforeEach((to, from, next) => {
  NProgress.start() // start progress bar
  // debugger
  if (getToken()) { //判断是否有token
    /* has token */
    if (to.path === '/login') {
      next({ path: '/' })
      NProgress.done() // 
    } else {
      if (store.getters.addRouters.length === 0) {
        store.dispatch('GetUserInfo').then(() => {
          store.dispatch('GenerateRoutes', { }).then(() => {
            next({ ...to, replace: true })
          })
        })
      } else {
        next()
        NProgress.done()
      }
    }
  } else {
    if (to.path == '/login') { // 如果是登录页面路径,就直接next()
      next()
      NProgress.done()
    } else { // 不然就跳转到登录;
      next('/login')
    }
  }
})

GetUserInfo 仓库方法 获取存在缓存中的用户信息,然后再存在仓库里面

  GetUserInfo ({ commit, state }) {
      return new Promise((resolve, reject) => {
        let userinfo = JSON.parse(getUser())
        commit('SET_AVATAR', userinfo.Avatar)
        commit('SET_NAME', userinfo.Name)
        resolve()
      })
    },

GenerateRoutes这个是设置获取路由的方法

GenerateRoutes ({ commit }, data) {
      return new Promise(resolve => {
        // 获取缓存中的菜单信息
        if (getModule()) {
          let menu = JSON.parse(getModule())
          let routers = []
          generaMenu(routers, menu)
          commit('SET_ROUTERS', routers)
          resolve()
        } else {
          // 没有就请求接口 获取菜单接口
          req.get('System/GetSysModule', {}).then(res => {
            if (res.StatusCode === 200) {
              // 设置缓存
              setModule(JSON.stringify(res.Data))
             let routers = []
              generaMenu(routers, res.Data)
              //
              commit('SET_ROUTERS', routers)
              resolve()
            } else {
              resolve()
            }
          })
        }
      })
    }

generaMenu 这个方法 把后台返回的菜单组装成 路由的集合

function generaMenu (routers, data) {
  data.forEach((item) => {
    let menu = {
      path: item.MUrl,
	//这里的lazyLoading 可以替换成 () => import(`@/views${item.MUrl}`) 我这里是封装了一个方法
      component: !item.MUrl ? Layout : lazyLoading(item.MUrl),
      hidden: true,
      children: [],
      name: item.MUrl,
      meta: {title: item.MName, icon: item.MIcon, id: item.ID}
    }
    if (item.Childrens) {
      generaMenu(menu.children, item.Childrens)
    }
    routers.push(menu)
  })
}

下面是permission.js 的完整代码

import { asyncRouterMap, constantRouterMap } from '@/router'
import { getModule, setModule } from '@/utils/auth'
import lazyLoading from '@/utils/lazyLoading'
import req from '@/utils/req'
import Layout from '@/views/Layout/index'
// import moudle from '@/views/system/moudle'
import router from '@/router'
function generaMenu (routers, data) {
  data.forEach((item) => {
    let menu = {
      path: item.MUrl,
      component: !item.MUrl ? Layout : lazyLoading(item.MUrl),
      hidden: true,
      children: [],
      name: item.MUrl,
      meta: {title: item.MName, icon: item.MIcon, id: item.ID}
    }
    if (item.Childrens) {
      generaMenu(menu.children, item.Childrens)
    }
    routers.push(menu)
  })
}
const permission = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers
      state.routers = constantRouterMap.concat(routers)
      //这里将动态组装的路由添加到路由里面
      router.addRoutes(state.routers)
    }
  },
  actions: {
    GenerateRoutes ({ commit }, data) {
      return new Promise(resolve => {
        // 获取缓存中的菜单信息
        if (getModule()) {
          let menu = JSON.parse(getModule())
          let routers = []
          generaMenu(routers, menu)
          commit('SET_ROUTERS', routers)
          resolve()
        } else {
          // 没有就请求接口 获取菜单接口
          req.get('System/GetSysModule', {}).then(res => {
            if (res.StatusCode === 200) {
              // 设置缓存
              setModule(JSON.stringify(res.Data))
              let routers = []
              generaMenu(routers, res.Data)
              commit('SET_ROUTERS', routers)
              resolve()
            } else {
              resolve()
            }
          })
        }
      })
    }
  }
}

export default permission

下面是 router 里面的代码

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

export const constantRouterMap = [
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  }
]
export default new Router({
  // mode: 'history', // require service support
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRouterMap
})

export const asyncRouterMap = [

]
二、 找到仓库的存放的导航菜单信息,展示到左侧

写了一个公用的组件 NavMenu 在引用的时候获取 存在仓库里面的路由

<template>
  <div class="navMenu " :class="isCollapse?'collapseY':'collapseN'">
    <label v-for="(navMenu,index) in navMenus" :key="index">
        <!-- <router-link :to="navMenu.entity.value"> -->
            <el-menu-item v-if="navMenu.children.length==0&&navMenu.meta.id" @click="goRouter(navMenu.path)"
                      :key="navMenu.path" :data="navMenu" :index="navMenu.path"
                    >
            <i :class="navMenu.meta.icon"  style="margin-right:5px;"></i>
             <span slot="title" >{{navMenu.meta.title}}</span>
            </el-menu-item>
        <!-- </router-link> -->
      <el-submenu v-if="navMenu.children.length>0"
                  :key="navMenu.meta.id" :data="navMenu" :index="navMenu.path">
        <!-- <router-link :to="navMenu.entity.value"> -->
          <template slot="title"  @click="goRouter(navMenu.path)">
            <i :class="navMenu.meta.icon"></i>
            <span> {{navMenu.meta.title}}</span>
          </template>
        <!-- </router-link> -->
        <NavMenu :navMenus="navMenu.children" :isCollapse='isCollapse'></NavMenu>
      </el-submenu>
    </label>
  </div>
</template>

然后 在一个写一个公用的layout 组件引用 ,
效果如下
在这里插入图片描述

结束语

可能写的不好,希望大神们反馈

  • 25
    点赞
  • 150
    收藏
    觉得还不错? 一键收藏
  • 43
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值