因为,如果我们的导航栏没有这个权限,输入对应网址,一样可以获取对应的页面,为了解决这个问题,有两种解决方案,一种是动态路由绑定(导航有多少个,就有多少个路由,在路由修改之前,先进行一个导航路由的加载和路由的动态绑定,然后看是否有这个路由,有就跳转),一种是权限的校验(路由修改之前,进行一个拦截,对用户的权限进行一个校验),这两种方法都可以在路由页面里,使用beforeEach来进行操作,这里是动态路由绑定
将这个用户的能显示显示的导航栏对应的路由,和我们的路由配置进行一个绑定和校验,这样的话,如果说没有这个用户对应的路由,那么就无法跳转到对应的页面
因为还没写后端,所以使用mock.js来模拟一下
- Mock.mock('/sys/menu/nav', 'get', () => {
- let nav = [
- {
- name: 'SysManga',
- title: '系统管理',
- icon: 'el-icon-s-operation',
- component: "",
- path: '',
- children: [
- {
- name: 'SysUser',
- title: '用户管理',
- icon: 'el-icon-s-custom',
- component: "sys/User",
- path: '/sys/user',
- children: []
- }
- ]
- },
- {
- name: 'SysTools',
- title: '系统工具',
- icon: 'el-icon-s-tools',
- path: '',
- component: "",
- children: [
- {
- name: 'SysDict',
- title: '数字字典',
- icon: 'el-icon-s-order',
- path: '/sys/dicts',
- component: "sys/Dict",
- children: []
- },
- ]
- },
- ]
- let authoritys = [];
- Result.data = {
- nav: nav,
- authoritys: authoritys
- }
- return Result;
- });
将我们需要再其他页面使用的变量和方法写入
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- Vue.use(Vuex)
-
- export default {
- state: {
- menuList: [],
- authoritys: [],
- validation: false,
-
- },
- getters: {
- },
- mutations: {
- // 菜单列表
- setMenuList(state, menu) {
- state.menuList = menu
- },
- // 权限列表
- setPermList(state, perms) {
- state.authoritys = perms
- },
- setValidation(state, validation) {
- state.validation = validation;
- }
-
- },
- modules: {
- },
- actions: {
- },
- }
- <template>
- <el-menu
- class="el-menu-vertical-demo"
- background-color="#545c64"
- text-color="#fff"
- active-text-color="#ffd04b"
- @select="handleSelect"
- >
- <!-- 首页菜单项 -->
- <el-menu-item index="Index">
- <template #title>
- <i class="el-icon-s-home"></i>
- 首页
- </template>
- </el-menu-item>
- <!-- 系统管理子菜单 -->
- <el-submenu :index="menu.name" v-for="menu in menuList" :key="menu.name">
- <template #title>
- <i :class="menu.icon"></i>
- <span>{{ menu.title }}</span>
- </template>
- <!-- 用户管理子菜单 -->
- <el-menu-item
- v-for="item in menu.children"
- :key="item.name"
- :index="item.path"
- >
- <template #title>
- <i :class="item.icon"></i>
- <span>{{ item.title }}</span>
- </template>
- </el-menu-item>
- </el-submenu>
- </el-menu>
- </template>
-
- <script>
- export default {
- name: "SideMenu",
- data() {
- return {
-
- }
- },
- computed: {
- menuList: {
- get() {
- return this.$store.state.menu.menuList
- },
- }
- },
-
- methods: {
- handleSelect(index) {
- this.$router.push(index);
- },
-
- }
- }
- </script>
-
- <style scoped>
- .el-menu-vertical-demo {
- flex: 1; /* 菜单项占据 el-aside 的剩余空间 */
- overflow-y: auto; /* 如果内容过多,显示滚动条 */
- width: 200px;
- }
- </style>
- router.beforeEach((to, from, next) => {
- const validation = store.state.menu.validation;
- if (!validation) {
- axios.get("/sys/menu/nav", {
- headers: {
- Authorization: localStorage.getItem("token"),
- }
- }).then(res => {
- // 拿到 menuList
- store.commit("setMenuList", res.data.data.nav);
- // 拿到用户权限
- store.commit("setPermList", res.data.data.permList);
-
- // 动态绑定路由
- store.state.menu.menuList.forEach(item => {
- if (item.children) {
- item.children.forEach(e => {
- if (e.component) {
- router.addRoute("Home", {
- path: e.path,
- name: e.name,
- component: () => import(`@/views/${e.component}`),
- });
- }
- });
- }
- });
-
- // 更新 validation 状态
- console.log(123456)
- store.commit('setValidation', true);
-
- // 确保在异步操作完成后继续导航
- next({path: to.fullPath});
- }).catch(error => {
- console.error('Error fetching menu:', error);
- // 处理请求失败的情况,例如重定向到登录页面
- next('/login');
- });
- } else {
- // 如果已经验证过,直接继续导航
- next();
- }
- });