tortoisegit 第一次push 没有权限_vue如何实现路由权限控制

前言

在实际的开发过程中,我们通常会涉及到权限的问题,不同的用户进来只能看到他对应的菜单权限,页面上的菜单渲染是比较好实现的,这里就不多提,唯一比较难的就是路由的权限控制。

解决思路

目前大概有两种思路可以实现路由的权限控制:

1.通过router.beforeEach() 路由拦截的方式实现。

2.通过vue-router 官方提供的addRoutes()来进行动态路由注入,注意 该方法只有vue-router的版本 >= 2.2才有效。

我们可以来看这两种方式是如何实现的:

解决方案

路由拦截的方式

这种方式依赖于我们项目的路由表都是事先配置好的,假设我们的路由表有:

const router = new Router({
  routes: [{
        path: '/',
        redirect: '/index1'
    }, {
        path: '/index1',
        name: 'Index1',
        component: Index1
    }, {
        path: '/index2',
        name: 'Index2',
        component: Index2
    }, {
        path: '/index3',
        name: 'Index3',
        component: Index3
    }]
})

export default router;

router/index 中,通过router.beforeEach() 路由拦截去进行权限判断:

router.beforeEach((to, from, next) => {
    //to: 从哪个路由来
    //from: 去哪个路由
    //next:是一个方法,使用路由拦截,必须在后面添加next(),否则路由无法跳转

    //假设我们从后台获取的权限为:
    const list = ['index1', 'index2'];

    //如果没有匹配到,证明没有权限
    if(list.indexOf(to.name) === -1) {
        //next('/login');

        ... //或者执行其他操作
    }

    //路由拦截可根据项目返回的权限自行调整,这里只是做了一个简单的例子
})

到这里,我们就已经完成了第一种方案的路由权限控制,不过个人感觉算是比较low的一种方案,接下来,我们来重点看看第二种方案

动态注入路由

这种方式我们只需要配置静态的路由表,比如登录、注册页,其他路由通过动态注入:

const router = new Router({
  routes: [{
        path: '/',
        redirect: '/login'
    }, {
        path: '/login',
        name: 'login',
        component: Login
    }]
})

export default router;

假设我们在 登录 的时候,后端返回的权限列表如下:

//leaf: 是我们用来判断是否唯一的
//component:一般来说后端返回给我们的就是一个路径而已,所以我们需要自行的去加载组件
export const routers = [{
    path: '/main',
    name: 'main',
    leaf: false,
    component: 'pages/main',
    children: [{
        path: '/main/index1',
        name: 'index1',
        component: 'pages/index1',
        leaf: true
    }, {
        path: '/main/index2',
        name: 'index2',
        component: 'pages/index2',
        leaf: true
    }, {
        path: '/main/index3',
        name: 'index3',
        component: 'pages/index3',
        leaf: true
    }, {
        path: '/main/index4',
        name: 'index4',
        component: 'pages/index4',
        leaf: true
    }]
}, {
    path: '*',
    component: 'pages/noFind',
    leaf: true
}]

可以写个方法去再次过滤返回回来的路由列表

/**
 * @param routers 初始数据,为数组格式,一般来说是个空数组
 * @param data 后端返回的路由列表数据
 */
function generaMenu(routers, data) {
  data.forEach((item)=>{
    let menu = Object.assign({},item);
    menu.component = import(`@/${menu.component}.vue`);
    if(!item.leaf) {
      menu.children = [];
      generaMenu(menu.children,item.children);
        menu.redirect = menu.children[0].path; //如果需要重定向的话,可以根据自己的需求进行选择
    }
    routers.push(menu);
  })
}

注意 如果有用到404的路由话,需要把404这个路由放到整个路由表的最后一个,否则,因为一开始我们是没有对应的动态路由,默认就跳转到了404页面了,所以静态路由表不配置404路由,与动态路由一起注入到路由表中。

这样我们最终就得到了符合路由规则的路由表了。然后通过 addRoutes() 这个方法把路由给注入到路由表里面,之后就可以访问已注入的路由了:

this.$route.addRoutes(data);

注意 因为使用了addRoutes()这个方法之后,路由表已经可以认为是不可控的了,也就是说,已经注入的路由,没办法在通过官方给的api删除掉(当然,目前官方也没有提供相应的api)。那当我们A帐号退出之后,B帐号登录进来,也会执行 addRoutes() 这个方法,会一直累加上去,然后控制台上也会有警告,出现了重复的路由,然后我们访问A帐号有,B帐号没有的路由时,发现是可以进行访问的。这显然不符合我们的需求。

那么,我们该如何解决这个问题呢?

一种是在用户退出的时候,进行项目的重载:

location.href = '/'; //这种相对来说体验就非常差了,相当于重新刷新了页面,显然也是不符合我们的需求

还有一种就是重新初始化静态路由表: 首先,我们要对 router/index 进行改造一下:

const createRouter = () => new Router({
  routes: [{
    path: '/',
    redirect: '/login'
  }, {
    path: '/login',
    name: 'login',
    component: Login
  }]
})

const router = createRouter()

//重新实例化一个新的路由表,替换之前的路由表,然后将这个方法导出
export function resetRouter() {
  const newRouter = createRouter();
  router.matcher = newRouter.matcher; // the relevant part
}

然后,我们在用户退出的时候,重新执行下 resetRouter() 这个方法就可以重新初始化静态路由表,同时也发现B账号进来之后,只能访问对应的路由权限而已。A账号的权限路由已经不存在了。

结语

这是我个人对于路由权限控制的一点理解,如果文中有错误的地方,或者还有其他更好的方案的话,欢迎提出。

你可能感兴趣的:(tortoisegit,第一次push,没有权限,vue,判断同一数组内的值是否一直,vue中如何实现内嵌页面,vue中如何返回历史路由,vue路由重定向到登录页面,后端路由重定向代码)