权限控制

158 阅读2分钟

动态添加路由

  • 菜单权限控制(菜单中的页面是否能被访问)
  • 静态配置的路由时直接在routes里面进行配置,但是动态路由是通过 router.addRoutes() 进行配置

router/index.js

import Vue from "vue";
import VueRouter from "vue-router";
​
import aaaRouter from "./modules/aaa"; 
import bbbRouter from "./modules/bbb";  
import cccRouter from "./modules/ccc";  
​
import Layout from "@/layout";
​
Vue.use(VueRouter);
​
// 动态路由表,项目中不同的用户可以访问不同的功能
export const asyncRoutes = [
    aaaRouter,
    bbbRouter,
    cccRouter,
]
​
//静态路由
export const constantRoutes = [
    {
        path: '/',
        component: Layout,
        redirect: '/index',
        children: [
            {
                path: '/index',
                name: 'index',
                meta: { title: "首页" },
                component: () => import('@/views/index/index.vue'),
            },
        ]
    },
    {
        path: '/login',
        component: () => import('@/views/login/login.vue'),
    },
​
    {
        path: '/refresh',
        component: resolve => require(['@/views/refresh.vue'], resolve),
        meta: {
            title: '路由刷新'
        }
    },
    {
        name: '404',
        path: '/404',
        component: () => import('@/views/notFound/index.vue')
    },
    // {
    //  path: '*',    // 此处需特别注意至于最底部
    //  redirect: '/404'
    // }
];
​
const createRouter = () => new VueRouter({
    // mode: "history",
    scrollBehavior: () => ({ y: 0 }),//切换路由始终保持页面顶部
    routes: constantRoutes //constantRoutes为默认路由
})
const router = createRouter();
​
export function resetRouter() { //这个是重置函数
    const newRouter = createRouter();
    router.matcher = newRouter.matcher;
}
​
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
    return originalPush.call(this, location).catch(err => err)
}
​
export default router;

store/modules/permission.js

import { constantRoutes } from "@/router";
​
import https from "@/https/index/index.js";
​
const state = {
  menuList: [],//用户的路由权限
  routes: [],//筛选的静态+动态路由
}
​
const mutations = {
  setMenuList(state, payload) {//用户的路由权限
    state.menuList = payload
  },
​
  setRoute(state, route){ //筛选的静态+动态路由
    state.routes = [...constantRoutes, ...route]
  }
}
​
const actions = {
  setMenuList({ commit }) {
    return new Promise((resolve) => {
      //获取用户的路由权限
      https.getMenuList().then((res) => {
        if (res.data.code == 200) {
          commit("setMenuList", res.data.data); 
          resolve(res.data.data);
        }
      })
    });
  },
}
​
const getters = {
​
};
​
export default {
  namespaced: true,//命名空间
  state,
  mutations,
  actions,
  getters
};
​

src/permission.js

  • 动态添加路由-使用路由导航守卫
  • 最后添加404页面
  • 使用router.addRoutes()添加路由
  • 注意:新版本router.addRoutes已废弃:使用 router.addRoute()代替,只能router.addRoute() 遍历数组一条一条添加
import router, { asyncRoutes } from "@/router";
import store from "@/store";
import { Message } from "element-ui";
​
const whiteList = ["/login", "/404"]; // 白名单
// 1.,每次路由切换首先根据token判断用户是否登录
let hasRoutes = true  //解决router.addRoutes多次添加路由重复问题
​
router.beforeEach(async (to, from, next) => {
  let token = sessionStorage.getItem("token");
​
  if (token) {
    if (to.path === "/login") {
      console.log('to.path =login');
      next({ path: "/" });      // 已登录 跳转主页
    } else {
      try {
        if (hasRoutes) {
          const menus = await store.dispatch('permission/setMenuList')
          const menusUrlList = []
          menus.forEach((item) => {
            menusUrlList.push(item.url)
          }
        //在全部动态路由筛选出用户拥有的路由列表
          const filterRoute = asyncRoutes.filter(item => {
            return menusUrlList.includes(item.path)
          })
          filterRoute.push({ path: '*', redirect: '/404', hidden: true })
          router.addRoutes(filterRoute)
          store.commit('permission/setRoute', filterRoute) 
          hasRoutes = false  //解决动态路由刷新问题
          next({ ...to, replace: true });// replace: true, 导航中将留下 history 记录
        } else {
          next()
        }
      } catch (error) {
        // 删除token,跳转登录页面
        Message.error(error || "请重新登录");
      }
    }
  } else {
    /* 没有token*/
    if (whiteList.indexOf(to.path) !== -1) {
      //白名单列表
      next();
    } else {
      next(`/login`);
    }
  }
});
​
router.afterEach(() => {
});