Vue 全局守卫结合addRoute实现路由权限控制

思路就是前端写好全部的菜单信息,通过接口从后端拿相应权限。拿到之后使用全局守卫结合addRoute实现路由权限控制。

在日常开发中路由权限控制是经常遇到的,以下是我的部分代码实现:

名词解释:

全局守卫:

全局路由守卫每次都判断用户是否已经登录,没有登录则跳到登录页。已经登录(已经取得后台返回的用户的权限信息(角色之类的)),则判断当前要跳转的路由,用户是否有权限访问(根据路由名称到全部路由里找到对应的路由)。没有权限则跳到事先定义好的界面(403,404之类的)。

addRoute:

addRoutes允许在应用初始化之后,动态的挂载路由。

实现:

第一步:

应用初始化的时候先挂载不需要权限控制的路由,比如登录页,404等错误页。

// router.js 初始化界面
import Vue from "vue";
import VueRouter from "vue-router";
import Layout from "../views/layout/Layout";

Vue.use(VueRouter);

const routes = [
  {
    path: "/login",
    name: "login",
    component: () => import("../views/login/login")
  },
  {
    path: "/404",
    name: "404",
    component: () => import("../views/errorPage/404")
  }
];

const router = new VueRouter({
  mode: "history",
  base: "/sdd/",
  routes
});

export default router;

第二步:

全局路由守卫结合addRoute实现路由动态控制。

// permission.js 文件在main.js中直接引入 
import router from "./router";
import NProgress from "nprogress";// 一个进度条控制组件
import "nprogress/nprogress.css";
import store from "./store";
import { generateMenu } from "./views/layout/components/utils/menu";

NProgress.configure({ showSpinner: false }); // 固定搭配
const whiteList = ["/login"]; // 白名单

router.beforeEach(async (to, from, next) => {
  NProgress.start();
  if (sessionStorage.token) {
    if (to.path === "/login") {
      next({ path: "/" });
      NProgress.done();
    } else {
      // 获取当前用户信息
      if (from.path === "/login" || !store.state.user.userInfo.username) {
        const res = await store.dispatch("user/getUserInfo");
        if (res.code !== 0) {
          if (res.code !== 5002) {
            sessionStorage.removeItem("token");
            next({ path: "/login" });
            NProgress.done();
          }
        } else {
          // 获取用户权限
          if (store.state.user.routes.length === 0) {
            store
              .dispatch("user/listMenus")
              .then(res => {
                // 路由遍历为树的形式
                const routes = generateMenu(res.data) || []; 
                store.dispatch("user/setRoutes", routes);
                routes.push({
                  path: "*",
                  redirect: "/404"
                });
                
                router.addRoutes(routes); // 动态添加可访问路由表
                next({ ...to, replace: true }); // hack方法 确保addRoutes已完成
              })
              .catch(() => {
                sessionStorage.removeItem("token");
                next({ path: "/login" });
                NProgress.done();
              });
          } else {
            next();
          }
        }
      } else {
        next();
      }
    }
  } else {
    // 白名单上的path 直接next()
    if (whiteList.includes(to.path)) {
      next();
    } else {
      next({ path: "/login" });
      NProgress.done();
    }
  }
});

router.afterEach(() => {
  NProgress.done();
});

generateMenu 方法实现:

import Layout from "../../Layout";

const menuMap = {
  // 首页
  home_page: {
    path: "/",
    icon: "Dashboard",
    component: Layout
  },
  // 客户端用户
  client_user_module: {
    path: "/client-setting",
    icon: "clientUser",
    component: Layout
  },
  client_user_manager_submodule: {
    path: "user",
    icon: "clientUser",
    component: () => import("../../../clientSetting/clientUser/clientUser")
  },
  client_user_template_submodule: {
    path: "authority",
    icon: "template",
    component: () =>
      import("../../../clientSetting/clientAuthority/clientAuthority")
  },
  client_user_announcement_submodule: {
    path: "notice",
    icon: "notice",
    component: () =>
      import("../../../clientSetting/clientSendNotice/clientSendNotice")
  },
  // 镜像管控
  image_manager_module: {
    path: "/system-image",
    icon: "SystemImage",
    component: Layout
  },
  image_manager_submodule: {
    path: "management",
    icon: "SystemImage",
    component: () =>
      import("../../../systemImage/systemImageManagement/systemImageManagement")
  },
  // 终端管控
  terminal_manager_module: {
    path: "/terminal-management",
    icon: "Terminal",
    component: Layout
  },
  terminal_manager_submodule: {
    path: "management",
    icon: "Terminal",
    // prettier-ignore
    component: () =>
      import("../../../terminalManagement/terminalManagement/terminalManagement")
  },
  firmware_upgrade_submodule: {
    path: "firmware-upgrade",
    icon: "Upgrade",
    component: () =>
      import("../../../terminalManagement/firmwareUpgrade/firmwareUpgrade")
  },
  // 资产统计
  asset_manager_module: {
    path: "/asset-statistics",
    icon: "Asset",
    component: Layout
  },
  asset_hardware_submodule: {
    path: "hardware",
    icon: "Hardware",
    component: () => import("../../../assetStatistics/hardware/hardware")
  },
  // 审计管理
  audit_manager_module: {
    path: "/audit-management",
    icon: "Audit",
    component: Layout
  },
  system_log_submodule: {
    path: "systemLog",
    icon: "systemLog",
    component: () => import("../../../auditManagement/systemLog/systemLog")
  },
  web_log_submodule: {
    path: "webLog",
    icon: "webLog",
    component: () => import("../../../auditManagement/webLog/webLog")
  },
  illegality_connect_log_submodule: {
    path: "illegalOutreachLog",
    icon: "illegalLog",
    component: () =>
      import("../../../auditManagement/illegalOutreachLog/illegalOutreachLog")
  },
  device_safe_log_submodule: {
    path: "deviceSecurityLog",
    icon: "deviceLog",
    component: () =>
      import("../../../auditManagement/deviceSecurityLog/deviceSecurityLog")
  },
  alarm_log_submodule: {
    path: "alarm-log",
    icon: "Alarm",
    component: () => import("../../../auditManagement/alarmLog/alarmLog")
  },
  asset_hardware_change_log_submodule: {
    path: "hardware-log",
    icon: "HardwareLog",
    component: () => import("../../../auditManagement/hardwareLog/hardwareLog")
  },
  power_control_log_submodule: {
    path: "power-log",
    icon: "Power",
    component: () => import("../../../auditManagement/powerLog/powerLog")
  },
  // 系统设置
  system_config_module: {
    path: "/system-setting",
    icon: "Setting",
    component: Layout
  },
  global_config_submodule: {
    path: "param",
    icon: "params",
    component: () => import("../../../systemSetting/systemParam/systemParam")
  },
  sysuser_manager_submodule: {
    path: "user",
    icon: "systemUser",
    component: () => import("../../../systemSetting/systemUser/systemUser")
  },
  sysrole_manager_submodule: {
    path: "role",
    icon: "systemRole",
    component: () => import("../../../systemSetting/systemRole/systemRole")
  },
  data_clear_submodule: {
    path: "dataClean",
    icon: "dataClean",
    component: () =>
      import("../../../systemSetting/systemDataClean/systemDataClean")
  },
  resource_center_submodule: {
    path: "resource-center",
    icon: "ResourceCenter",
    component: () =>
      import("../../../systemSetting/resourceCenter/resourceCenter")
  },
  // 系统帮助
  system_help: {
    path: "/help",
    icon: "Help",
    component: Layout
  },
  system_help_about: {
    path: "about",
    icon: "About",
    component: () => import("../../../help/about/about")
  }
};

export function generateMenu(menu) {
  // 两级菜单
  const travelMenu = menu => {
    let routes = [];
    for (let item of menu) {
      let route = {};
      route.name = item.moduleName;
      route.path = menuMap[item.moduleId] && menuMap[item.moduleId].path;
      route.component =
        menuMap[item.moduleId] && menuMap[item.moduleId].component;
      route.icon = menuMap[item.moduleId] && menuMap[item.moduleId].icon;
      if (item.childModules && item.childModules.length > 0) {
        route.children = travelMenu(item.childModules);
      }
      if (route.path && route.component) {
        routes.push(route);
      }
    }
    // 添加重定向
    routes.forEach(item => {
      if (item.path === "/") {
        item.redirect = "/dashboard";
        item.children = [
          {
            path: "dashboard",
            component: () => import("../../../dashboard/dashboard"),
            name: item.name
          }
        ];
      } else if (item.children) {
        item.redirect = item.path + "/" + item.children[0].path;
      }
    });
    return routes;
  };
  return travelMenu(menu);
}

 

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3中,可以使用router.addRoute()方法实现动态路由的添加。这个方法可以接受两个参数,第一个参数可以是父级路由对象或者父级路由的路径,第二个参数是要添加的路由对象。通过调用这个方法,可以动态地向路由中添加单个路由。\[1\] 以下是一个示例代码,展示了如何在Vue3中使用addRoute()方法实现动态路由的添加: ```javascript import { createRouter } from 'vue-router' const router = createRouter({ // 路由配置 }) // 添加单个路由 const route = { path: '/dynamic', name: 'Dynamic', component: () => import('@/views/Dynamic.vue') } router.addRoute(route) export default router ``` 在上面的代码中,我们首先创建了一个路由实例,然后定义了一个要添加的路由对象。最后,通过调用addRoute()方法将这个路由对象添加到路由中。 需要注意的是,在Vue3中,使用addRoute()方法添加的路由会立即生效,无需重新创建路由实例或调用其他方法。这样,新添加的路由就可以在页面上进行渲染了。 希望这个回答对你有帮助! #### 引用[.reference_title] - *1* *3* [vue3动态路由addRoute](https://blog.csdn.net/m0_49343686/article/details/123959075)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [vue3 使用addRoute动态添加路由,兼解决刷新空白或跳到404页面问题](https://blog.csdn.net/YSQ_qsy/article/details/122042229)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值