🔥 快速配置vue3 vue-router4管控权限动态路由

1,165 阅读2分钟

截屏2022-05-14下午5.02.25.png

截屏2022-05-14下午5.01.50.png

介绍

vue.js官方路由。让我们在构建单页面变得简单。

安装

npm install vue-router@4

用vite直接创一个vue3项目出来

npm init vue@latest
✔ Project name: … <your-project-name>
✔ Add TypeScript? … Yes // 选择ts 一般选这个ts(多人开发,毕竟vue3都改成适应ts了,会比不会好)
✔ Add JSX Support? … No
✔ Add Vue Router for Single Page Application development? … Yes // 选router 这个默认给我们上vue-router4(最新的)
✔ Add Pinia for state management? … Yes // 选pinia 上vue3推荐选这个管理状态
✔ Add Vitest for Unit testing? … No
✔ Add Cypress for both Unit and End-to-End testing? … No
✔ Add ESLint for code quality? … Yes // 选eslint来约束一下代码质量
✔ Add Prettier for code formatting? … No

Done.

目录结构:

截屏2022-05-14下午4.40.49.png

main.ts

import router from './router'
app.use(router)

App.vue

<template>
  <RouterView />
</template>

router/index.ts

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
const Layout = () => import('@/layout/index.vue')

// 配一个常量的路由,放不用权限控制的,例如登录页、首页、404等页面

export const constantRoutes: RouteRecordRaw[] = [
  {
    path: '/login',
    name: 'login',
    component: () => import('@/views/login/index.vue')
  },
  {
    path: '/',
    name: 'dashboard',
    redirect: '/dashboard',
    component: Layout,
    children: [
      {
        path: 'dashboard',
        component: () => import('@/views/dashboard/index.vue'),
        name: 'Dashboard',
        meta: {
          title: '首页',
          icon: 'dashboard'
        }
      }
    ]
  },
  {
    path: '/404',
    component: () => import('@/views/error-page/404.vue'),
  }
]


// 配一个需要权限管控的路由模块,根据角色来控制

export const asyncRoutes: RouteRecordRaw[] = [
  {
    path: '/permission',
    name: 'Permission',
    redirect: '/permission/index',
    component: Layout,
    meta: {
      title: '权限管理',
      icon: 'lock',
      roles: ['admin', 'editor'], // you can set roles in root nav
      alwaysShow: true // will always show the root menu
    },
    children: [
      {
        path: 'index',
        component: () => import('@/views/permission/index.vue'),
        name: 'PermissionIndex',
        meta: {
          title: '权限管理',
          roles: ['admin'] // or you can only set roles in sub nav
        }
      },
      {
        path: 'directive',
        component: () => import('@/views/permission/directive.vue'),
        name: 'PermissionDirective',
        meta: {
          title: '指令权限'
        }
      }
    ]
  },
  {
    path: '/:pathMatch(.*)',
    redirect: '/404',
    hidden: true
  }
]

// 一开始,没登录进来之前都只是createRouter的就只是常量路由,比如说登录页是任何人都可以看得,404也是如此;至于首页dashboard没登录进来之前有路由监听,虽说一开始也创了,但在路由监听router.beforeEach这里会把访问者也打到登录页,所以也进不去。

//  当然这里constantRoutes也可以不放首页,首页放到asyncRoutes这里路由也是可以的。

const router = createRouter({
  history: createWebHistory(),
  routes: constantRoutes
})

export default router

再者,在用户登录正确进去之后再去调用这个用户信息的接口,再去根据这个用户的角色去整理一下asyncRoutes这个角色应该看哪些路由。

const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) => {
  const res: RouteRecordRaw[] = [];
  routes.forEach((route) => {
    const tmp = { ...route };
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles);
      }
      res.push(tmp);
    }
  });
  return res;
};

再来,上一步得到了这个用户权限下能看得路由,放到了状态管理仓库里permissionStore.dynamicRoutes

router.beforeEach(async(to, from, next) => {
  NProgress.start();
  if (token.getToken()) {
    if (to.path === "/login") {
      next({ path: "/" });
      NProgress.done();
    } else {
      if (userStore.roles.length === 0) {
        // 检查用户是否已获得权限角色
        await userStore.getInfo();
        const roles = userStore.roles;
        permissionStore.setRoutes(roles)
        permissionStore.dynamicRoutes.forEach(v => {
          router.addRoute(v)
        })
        next({ ...to, replace: true });
      } else {
        next();
      }
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next();
    } else {
      next("/login");
      NProgress.done();
    }
  }
});

给这个用户加了他可看的路由,到此就已经完成了。

代码在这,自行拿取,祝您生活愉快!!!