1、修改permission.js文件

在vuex路径src\store\modules\permission.js下新建permission.js文件,该操作为最重要的一步,主要是从后端查询菜单并生成路由。

import { asyncRoutes, constantRoutes } from '@/router'
import { fetchUserMenuList } from '@/api/user'
import Layout from '@/layout'
 
/**
 * 静态路由懒加载
 * @param view  格式必须为 xxx/xxx 开头不要加斜杠
 * @returns
 */
export const loadView = (view) => {
  return (resolve) => require([`@/views/${view}.vue`], resolve)
}
 
/**
 * 把从后端查询的菜单数据拼装成路由格式的数据
 * @param routes
 * @param data 后端返回的菜单数据
 */
export function generaMenu(routes, data) {
  data.forEach(item => {
    const menu = {
      path: item.url,
      component: item.component === '#' ? Layout : loadView(item.component),
      hidden: item.status === 0, // 状态为0的隐藏
      redirect: item.redirect,
      children: [],
      name: item.code,
      meta: item.meta
    }
 
    if (item.children) {
      generaMenu(menu.children, item.children)
    }
    routes.push(menu)
  })
  return routes
}
 
const state = {
  routes: [],
  addRoutes: []
}
 
const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    // 拼接静态路由和动态路由
    state.routes = constantRoutes.concat(routes)
  }
}
 
const actions = {
  generateRoutes({ commit }, token) {
    return new Promise(resolve => {
      // 通过token从后端获取用户菜单,并加入全局状态
      fetchUserMenuList(token).then(res => {
        const menuData = Object.assign([], res.data)
        const tempAsyncRoutes = Object.assign([], asyncRoutes)
        const accessedRoutes = generaMenu(tempAsyncRoutes, menuData)
 
        commit('SET_ROUTES', accessedRoutes)
        resolve(accessedRoutes)
      }).catch(error => {
        console.log(error)
      })
    })
  }
}
 
export default {
  namespaced: true,
  state,
  mutations,
  actions
}

2、在getters中增加路由状态

​在vuex路径src\store\getters.js添加menusRoutes状态

menusRoutes: state => state.permission.routes

3、修改菜单生成数据来源

在路径src\layout\components\Sidebar\index.vue修改routes数据来源,原来数据源是路由,改为从vuex中获取。

routes() {
      // return this.$router.options.routes
      return this.$store.getters.menusRoutes
    },

​至此,从后端获取菜单数据到页面展示的逻辑已经完毕,下面开始在登陆后进行调用。

 4、登陆后获取菜单

在vuex路径src\store\modules\user.js的login方法中,加入登陆成功通过token获取菜单生成路由逻辑。

// 获取菜单,调用其他文件中actions时必须加 { root: true }
          dispatch('permission/generateRoutes', data, { root: true }).then((accessRoutes) => {
            router.addRoutes(accessRoutes)
          })

5、解决刷新后页面空白

​以上内容已经可以实现登陆后展示左侧菜单功能,但是会发现每次刷新页面后,页面都会变空白。这是因为在页面刷新时,会重新加载vue实例,vuex的store中的数据会被重新赋值,导致我们存在vuex中的路由信息被清空。

​在src\permission.js中增加重新获取路由代码。

const accessRoutes = await store.dispatch('permission/generateRoutes', store.getters.token)
          router.addRoutes(accessRoutes)
          next({ ...to, replace: true })

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐