vue 后台权限管理 以及过程中所遇到的问题

本次使用的是vue-admin-template-master模板

1.首先从后端那里获取用户权限的接口

2. 在路由导航里面每次跳转路由就向store派发一个获取用户权限接口

 // 获取用户信息  权限
 await store.dispatch('user/getInfo')

3.在store   actions里面调取用户权限接口以及储存用户权限到state里面

 // 获取用户权限
  async getInfo({
    commit,
    state
  }) {
    let res = await getRole();
    console.log(res);
    if (res.status == 0) {
      //vuex存储用户权限
      commit('SET_USERINFO', res);
      // 根据用户权限要展示的异步路由
      commit('SET_RESULTASYNCROUTES', computeRouting(asyncRoutes, res.data));
    }
  },
 // 存储用户信息
  SET_USERINFO: (state, res) => {
    // 路由权限
    state.routes = res.data;
    // 角色
    state.role = res.role;
  },
//state里面数据
onst getDefaultState = () => {
  return {
    token: getToken(),
    // 路由权限
    routes: [],
    // 角色
    role: '',
    // 根据用户权限要展示的异步路由
    resultAsyncRoutes: [],
    // 要展示的所有路由
    resultAllRoutes: [],
    isAddRoutes: false
  }
}

4.在router 里面把路由拆分为三部分:

constantRoutes  //常量路由   不管用户有没有权限都可以访问的路由  比如:首页  登录页面

asyncRoutes   //异步路由   根据用户的权限显示不同的路由

anyRoutes      //任意路由    放404页面   最后合并的时候把他放到最后

// 常量路由
export const constantRoutes = [{
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },

  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  },

  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    children: [{
      path: 'dashboard',
      name: 'Dashboard',
      component: () => import('@/views/dashboard/index'),
      meta: {
        title: '首页',
        icon: 'dashboard'
      }
    }]
  },
]
// 异步路由
export const asyncRoutes = [{
    path: '/price',
    name:'UserPrice',
    component: Layout,
    children: [{
      path: 'index',
      name: 'Price',
      component: () => import('@/views/price/index'),
      meta: {
        title: '用户产品',
        icon: 'form'
      }
    }]
  },

  {
    path: '/statistics',
    name: 'StatisticsManage',
    component: Layout,
    children: [{
      path: 'index',
      name: 'Statistics',
      component: () => import('@/views/statistics/index'),
      meta: {
        title: '统计管理',
        icon: 'form'
      }
    }]
  },
  {
    path: '/totalSearch',
    component: Layout,
    name: 'Total',
    children: [{
      path: 'index',
      name: 'totalSearch',
      component: () => import('@/views/totalSearch/index'),
      meta: {
        title: '总量查询',
        icon: 'form'
      }
    }]
  },
]
// 任意路由 当路径出现错误的时候,重定向到404
export const anyRoutes =
  // 404 页面必须放在末尾!!!
  {
    path: '*',
    redirect: '/404',
    hidden: true
  }

5.store  user.js文件里面 

引入已经分配好的路由以及router实例

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

6.根据接口返回来的用户权限来过滤出我们要展示的路由

// 根据用户权限要展示的异步路由
commit('SET_RESULTASYNCROUTES', computeRouting(asyncRoutes, res.data));

computeRouting函数用来过滤出要展示的路由

根据路由的name参数来进行过滤

// 过滤出要展示的路由
const computeRouting = (asyncRoutes, routes) => {

  return asyncRoutes.filter(item => {
    if (routes.indexOf(item.name) != -1) {
      // 使用递归过滤子路由
      if (item.children && item.children.length) {
        item.children = computeRouting(item.children, routes);
      }
      return true;
    }
  })
}

合并要展示的所有路由  使用addRoutes添加新的路由  最后储存到state里面

  // 根据用户权限要展示的异步路由
  SET_RESULTASYNCROUTES: (state, asyncRoutes) => {
    // 储存当前用户的异步路由
    state.resultAsyncRoutes = asyncRoutes;
    // 合并要展示的所有的路由
    state.resultAllRoutes = constantRoutes.concat(state.resultAsyncRoutes, anyRoutes);
    // 给路由器添加新的路由
    router.addRoutes(state.resultAllRoutes);
    state.isAddRoutes = true;
  }

7.在src/layout/components/Sidebar/index.vue文件里面遍历分配好的路由

<sidebar-item
   v-for="route in routes"
   :key="route.path"
   :item="route"
   :base-path="route.path"
/>

routes() {
   // return this.$router.options.routes
   // 遍历仓库中计算好的路由
   return this.$store.state.user.resultAllRoutes;
},

最后来说说做好权限路由之后遇到刷新页面白屏的问题

引起白屏的原因是使用addRoutes导致的

解决方法:

store user  state里面 定义几个变量 初始值为false

const getDefaultState = () => {
  return {
    isAddRoutes: false
  }
}

给路由器添加好新的路由之后让他的值为true

  // 根据用户权限要展示的异步路由
  SET_RESULTASYNCROUTES: (state, asyncRoutes) => {
    // 储存当前用户的异步路由
    state.resultAsyncRoutes = asyncRoutes;
    // 合并要展示的所有的路由
    state.resultAllRoutes = constantRoutes.concat(state.resultAsyncRoutes, anyRoutes);
    // 给路由器添加新的路由
    router.addRoutes(state.resultAllRoutes);
    state.isAddRoutes = true;
  }

在permission.js全局路由导航文件里面

    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({
        path: '/'
      })
      NProgress.done()
    } else {
      const hasGetUserInfo = store.getters.name
      if (hasGetUserInfo) {
        next()
      } else {
        try {
          if (!store.state.user.isAddRoutes) {
            // 获取用户信息  权限
            await store.dispatch('user/getInfo')
            // next()
            // 确保路由完整性,设置replace 为true 这样导航就不会留下历史记录。
            next({
              ...to, // next({ ...to })的目的,是保证路由添加完了再进入页面 (可以理解为重进一次)
              replace: true // 重进一次, 不保留重复历史
            })
          } else {
            next()
          }
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
next({
   ...to, // next({ ...to })的目的,是保证路由添加完了再进入页面 (可以理解为重进一次)
   replace: true // 重进一次, 不保留重复历史
})

最后在退出登录的时候重置路由

router文件:

// 重置路由
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // 重新设置路由的可匹配路径
}

在store/user.js文件里面

  // 退出
  logout({
    commit,
    state
  }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        removeToken() // must remove  token  first
        // 退出移除用户ID
        window.localStorage.removeItem('userId')
        window.localStorage.removeItem('username')
        // 重置路由
        resetRouter()
        commit('RESET_STATE')
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值