实现思路

vue实现菜单的权限控制主要有两种思路:

  • 在路由转发时添加路由拦截,即使用beforeEach拦截没有权限的路由,并跳转到404界面。不过这种实现方法具有一定的缺点,即每次路由切换时都会进行路由拦截的判断。

  • 动态添加路由,通过后端返回的菜单,为用户动态添加具有权限的路由。这种只会在系统初始化和页面刷新时调用。

重点是一定使用router.onReady实现,这种方法比判断store缓存是否存在更好用

一、beforeEach路由拦截

为了方便演示,我把后端返回的菜单路由数组存在sessionStorage中。即代码中的menuList。

// 免登陆白名单
const noLoginWhiteList = ['/login', '/404'];
router.beforeEach((to, from, next) => {
    if (noLoginWhiteList.includes(to.path)) {	// 如果前进的路由在白名单中则直接跳转
        next();
    } else if (getSession('userInfo')) {	// 如果用户已经登录
        const arr = getSession('menuList').map(item => {
            return item.url;	// 获取所有的有权限的url
        });
        if (arr.includes(to.path)) {
            next();		// 有权限则前进
        } else {
            next({
                path: '/404'	//无权限跳转到404
            })
        }
    } else {
        next({
            path: '/login'	//未登录跳转到登录
        })
    }
})

二、addRoutes+router.onReady 动态添加路由

1、技术介绍
  • addRoutes
    动态添加路由,且参数是必须符合路由规则的数组

  • router.onReady
    路由初始化时调用,每次当页面刷新时就相当于要初始化一次路由,这时候再调用一遍动态添加路由的方法就能避免跳转到404的错误。
    网上很多方法是将菜单信息存储到store中,每次判断store是否存在来判断是否刷新。但是使用onReady不管你如何存储的菜单信息,都可以解决问题。

2、具体步骤
  1. 定义路由(router下的index.js)
// 菜单项路由
export const menuRoute = [
    {
        path: '/index1',
        component: resolve => require(['@/views/index1/Index1.vue'], resolve)
    },
    {
        path: '/order',
        component: resolve => require(['@/views/order/Order.vue'], resolve)
    },
    {
        path: '/bill',
        component: resolve => require(['@/views/bill/Bill.vue'], resolve)
    },
    {
        path: '/user',
        component: resolve => require(['@/views/user/User.vue'], resolve),
        meta: { title: '销售品列收' },
    }
];

// 固定已有的路由
export default new Router({
    mode: 'history',
    routes: [{
        path: '/',
        redirect: '/user'
    },
    {
        path: '/login',
        component: resolve => require(['@/views/login/Login.vue'], resolve),
        meta: { title: '登录' },
    },
    {
        path: '/404',
        component: resolve => require(['@/components/error-page/404.vue'], resolve)
    }]
})
  1. 新建permission.js
import { getSession } from '@/utils/storage';
import router from './index';
import { menuRoute } from './index';

export function getPermission(){
    const menuList = getSession('menuList');	// 获取后端返回的路由
    const urls = menuList.map(item => {
        return item.url;
    })
    // 获取有权限的菜单路由(只是我自己项目中根据自己的数据结构的操作,具体看个人项目)
    let addGroup = menuRoute.filter(item => {
        return urls.includes(item.path);
    });
    const homeRoute = [
        {
            path: '/',
            redirect: menuList[0].url,
            component: resolve => require(['@/views/common/Home.vue'], resolve),
            children: addGroup
        },
        {
            path: '*',
            redirect: '/404'    // 匹配不到的路由一定到放在最后添加,否则页面刷新将跳转到404
        }
    ];
    router.addRoutes(homeRoute);	// 动态添加
}
  1. 登录成功后调用动态添加路由的方法
// 伪代码
import { getPermission } from '@/router/permission';

login(() => {
	getPermission();
})
  1. 在main.js添加每次刷新后的处理
// 登录成功时已经添加了一遍,登陆后刷新时才需要再次动态添加
// 页面刷新时重新动态添加路由
if(getSession('userInfo')){		// 是否登录
    router.onReady(() => {
        getPermission();
    })
}

哪里写的不好欢迎指正。

Logo

前往低代码交流专区

更多推荐