vue-element-admin 动态路由配置

后端路由格式

[

  {

    path: "/user", 

    component: 'Layout',

    alwaysShow: true,

    name: 'UserModule',

    meta: {title: "用户管理", icon: "el-icon-s-tools"},

    children: [

      { path: "user", 

        component: "user/user/index", 

        name: "UserModuleUser",

        meta: {title: "用户列表"}

      },

 

      { path: "role", 

        component: "user/role/index", 

        name: "UserModuleRole",

        meta: {title: "角色列表"}

      },

 

      { path: "center", 

        component: "user/center/index", 

        name: "UserModuleCenter",

        hidden: true,

        meta: {title: "个人中心"}

      }

    ] 

  }

];

 

src/store/permission.js

import { asyncRoutes,constantRoutes } from '@/router'

//constantRoutes 无权限控制页面

//asyncRoutes 权限控制页面

import { getInfo } from '@/api/user'

import Layout from '@/layout/index'

 

/**

 * Use meta.role to determine if the current user has permission

 * @param roles

 * @param route

 */

function hasPermission(roles, route) {

  if (route.meta && route.meta.roles) {

    return roles.some(role => route.meta.roles.includes(role))

  } else {

    return true

  }

}

 

/**

 * Filter asynchronous routing tables by recursion//通过递归过滤异步路由表

 * @param routes asyncRoutes

 * @param roles

 */

export function filterAsyncRoutes(routes, roles) {

    const res = []

 

    routes.forEach(route => {

        const tmp = {...route }//扩展运算符...

        if (hasPermission(roles, tmp)) {

            if (tmp.children) {

                tmp.children = filterAsyncRoutes(tmp.children, roles)

            }

            res.push(tmp)

        }

    })

 

    return res

}

 

const state = {

    routes: [],

    addRoutes: []

}

 

const mutations = {

    SET_ROUTES: (state, routes) => {

        state.addRoutes = routes

        state.routes = constantRoutes.concat(routes)

    }

}

 

const actions = {

    generateRoutes({ commit }) {

        return new Promise(resolve => {

          // 向后端请求路由数据

          getInfo().then(res => {

            const accessedRoutes = filterAsyncRouter(res.data.menus)

            accessedRoutes.push({path: '*', redirect: '/404', hidden: true})

            commit('SET_ROUTES', accessedRoutes)

            resolve(accessedRoutes)

          })

        })

    }

}

 

 

//读取本地的菜单,测试环境可用。生产环境不行。

// const actions = {

//   generateRoutes({ commit }, roles) {

//     return new Promise(resolve => {

//       let accessedRoutes

//       if (roles.includes('admin')) {

//         accessedRoutes = asyncRoutes || []

//       } else {

//         accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)

//       }

//       commit('SET_ROUTES', accessedRoutes)

//       resolve(accessedRoutes)

//     })

//   }

// }

 

// 遍历后台传来的路由字符串,转换为组件对象

export function filterAsyncRouter(asyncRouterMap) {

  return asyncRouterMap.filter(route => {

    if (route.component) {

      // Layout组件特殊处理

      if (route.component === 'Layout') {

        route.component = Layout

      } else {

        route.component = loadView(route.component)

      }

    }

    if (route.children != null && route.children.length != 0 && route.children && route.children.length) {

      route.children = filterAsyncRouter(route.children)

    }

    return true

  })

}

 

const loadView = (view) => require(`@/views/${view}`).default

 

export default {

    namespaced: true,

    state,

    mutations,

    actions

}

 

优化

刷新页面,userInfo 两次请求优化为一次。

src\permission.js

框架登录逻辑校验是

先通过 user/getInfo 获取用户信息(含用户角色 roles 数组)

然后将 roles 作为参数,请求 permission/generateRoutes 获取 路由

开发中:user/getInfo 和 permission/generateRoutes 调用的是同一个接口 userInfo。 使用  user/getInfo 就可以获取 角色(暂时用不上) 和路由。

考虑合并 src\store\modules\user.js 和  src\store\modules\permission.js  文件,改动有点麻烦,就使用以下的方式来减少一次请求。

if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
      NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
    } else {
      // determine whether the user has obtained his permission roles through getInfo
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        // 判断当前用户是否已拉取完user_info信息
        next()
      } else {
        try {
          // get user info
          // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
          // const { roles } = await store.dispatch('user/getInfo')
          const { menus } = await store.dispatch('user/getInfo')

          // generate accessible routes map based on roles
          const accessRoutes = await store.dispatch('permission/generateRoutes', menus)

          // dynamically add accessible routes
          router.addRoutes(accessRoutes)

          // hack method to ensure that addRoutes is complete
          // set the replace: true, so the navigation will not leave a history record
          next({ ...to, replace: true })
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch('user/resetToken')
          Message.error(error.message)
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    /* has no token*/

    if (whiteList.indexOf(to.path) !== -1) {
      // in the free login whitelist, go directly
      next()
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }

src\store\modules\user.js

// get user info
  getInfo({ commit, state }) {
    // console.log('第一次触发 getInfo')
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response
        const { info } = response.data
        const { roles } = response.data
        const { menus } = response.data
        if (!data) {
          reject('用户信息不存在!')
        }
        const { username, photo } = info
        if (!roles || roles.length <= 0) {
          reject('getInfo: roles must be a non-null array!')
        }
        commit('SET_ROLES', roles)
        commit('SET_MENUS', menus)
        commit('SET_NAME', username)
        commit('SET_AVATAR', photo)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

src\store\modules\permission.js

// const actions = {
//   generateRoutes({ commit },menus) {
//     return new Promise(resolve => {
//       // 向后端请求路由数据
//       // console.log('第二次触发 getInfo')
//       getInfo().then(res => {
//         const accessedRoutes = filterAsyncRouter(res.data.menus)
//         accessedRoutes.push({ path: '*', redirect: '/404', hidden: true })
//         commit('SET_ROUTES', accessedRoutes)
//         resolve(accessedRoutes)
//       })
//     })
//   }
// }

// 优化 getInfo 同时获取了角色(没用上)和权限菜单 少请求一次 getInfo
const actions = {
  generateRoutes({ commit }, menus) {
    return new Promise(resolve => {
      const accessedRoutes = filterAsyncRouter(menus)
      accessedRoutes.push({ path: '*', redirect: '/404', hidden: true })
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}

 

可能遇到的错误

1、Critical dependency: the request of a dependency is an expression

const loadView = (view) => require(`@/views/${view}`).default 

结尾的.default 别忘记加。

const loadView= (view) => import(`@/views/${view}.vue`)

.vue 后缀别忘记加。 

2、import 不识别变量,是依赖的版本问题,没找到解决办法。所以用require。

3、缺少依赖,不识别 require,用require项目运行卡住不动,用import运行正常。

const loadView = (view) => require(`@/views/${view}`).default

vue-loader at least v13.0.0+
npm install -D vue-loader vue-template-compiler

 

参考链接

https://panjiachen.github.io/vue-element-admin-site/zh/guide/advanced/lazy-loading.html#%E5%8C%BA%E5%88%86%E5%BC%80%E5%8F%91%E4%B8%8E%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83-%E8%AF%A5%E6%96%B9%E6%A1%88%E5%B7%B2%E6%B7%98%E6%B1%B0

https://github.com/PanJiaChen/vue-element-admin/issues/293

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Irene1991

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值