• 10.动态路由绑定怎么做


    为什么要动态路由绑定

    因为,如果我们的导航栏没有这个权限,输入对应网址,一样可以获取对应的页面,为了解决这个问题,有两种解决方案,一种是动态路由绑定(导航有多少个,就有多少个路由,在路由修改之前,先进行一个导航路由的加载和路由的动态绑定,然后看是否有这个路由,有就跳转),一种是权限的校验(路由修改之前,进行一个拦截,对用户的权限进行一个校验),这两种方法都可以在路由页面里,使用beforeEach来进行操作,这里是动态路由绑定

    思路

    将这个用户的能显示显示的导航栏对应的路由,和我们的路由配置进行一个绑定和校验,这样的话,如果说没有这个用户对应的路由,那么就无法跳转到对应的页面

    步骤(1-3步是准备步骤)

    1.使用mock.js返回对应的菜单栏和用户权限

    因为还没写后端,所以使用mock.js来模拟一下

    1. Mock.mock('/sys/menu/nav', 'get', () => {
    2. let nav = [
    3. {
    4. name: 'SysManga',
    5. title: '系统管理',
    6. icon: 'el-icon-s-operation',
    7. component: "",
    8. path: '',
    9. children: [
    10. {
    11. name: 'SysUser',
    12. title: '用户管理',
    13. icon: 'el-icon-s-custom',
    14. component: "sys/User",
    15. path: '/sys/user',
    16. children: []
    17. }
    18. ]
    19. },
    20. {
    21. name: 'SysTools',
    22. title: '系统工具',
    23. icon: 'el-icon-s-tools',
    24. path: '',
    25. component: "",
    26. children: [
    27. {
    28. name: 'SysDict',
    29. title: '数字字典',
    30. icon: 'el-icon-s-order',
    31. path: '/sys/dicts',
    32. component: "sys/Dict",
    33. children: []
    34. },
    35. ]
    36. },
    37. ]
    38. let authoritys = [];
    39. Result.data = {
    40. nav: nav,
    41. authoritys: authoritys
    42. }
    43. return Result;
    44. });

    2.在store里面写一个menu.js的页

    将我们需要再其他页面使用的变量和方法写入

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. Vue.use(Vuex)
    4. export default {
    5. state: {
    6. menuList: [],
    7. authoritys: [],
    8. validation: false,
    9. },
    10. getters: {
    11. },
    12. mutations: {
    13. // 菜单列表
    14. setMenuList(state, menu) {
    15. state.menuList = menu
    16. },
    17. // 权限列表
    18. setPermList(state, perms) {
    19. state.authoritys = perms
    20. },
    21. setValidation(state, validation) {
    22. state.validation = validation;
    23. }
    24. },
    25. modules: {
    26. },
    27. actions: {
    28. },
    29. }

    3.给对应的页面插入对应的元素

    1. <template>
    2. <el-menu
    3. class="el-menu-vertical-demo"
    4. background-color="#545c64"
    5. text-color="#fff"
    6. active-text-color="#ffd04b"
    7. @select="handleSelect"
    8. >
    9. <!-- 首页菜单项 -->
    10. <el-menu-item index="Index">
    11. <template #title>
    12. <i class="el-icon-s-home"></i>
    13. 首页
    14. </template>
    15. </el-menu-item>
    16. <!-- 系统管理子菜单 -->
    17. <el-submenu :index="menu.name" v-for="menu in menuList" :key="menu.name">
    18. <template #title>
    19. <i :class="menu.icon"></i>
    20. <span>{{ menu.title }}</span>
    21. </template>
    22. <!-- 用户管理子菜单 -->
    23. <el-menu-item
    24. v-for="item in menu.children"
    25. :key="item.name"
    26. :index="item.path"
    27. >
    28. <template #title>
    29. <i :class="item.icon"></i>
    30. <span>{{ item.title }}</span>
    31. </template>
    32. </el-menu-item>
    33. </el-submenu>
    34. </el-menu>
    35. </template>
    36. <script>
    37. export default {
    38. name: "SideMenu",
    39. data() {
    40. return {
    41. }
    42. },
    43. computed: {
    44. menuList: {
    45. get() {
    46. return this.$store.state.menu.menuList
    47. },
    48. }
    49. },
    50. methods: {
    51. handleSelect(index) {
    52. this.$router.push(index);
    53. },
    54. }
    55. }
    56. </script>
    57. <style scoped>
    58. .el-menu-vertical-demo {
    59. flex: 1; /* 菜单项占据 el-aside 的剩余空间 */
    60. overflow-y: auto; /* 如果内容过多,显示滚动条 */
    61. width: 200px;
    62. }
    63. </style>

    4.在路由页面写入beforeEach方法(有注释的)

    思路:

    1.在路由改变时发一个请求,拿到对应的菜单栏和权限

    2.动态绑定路由

    2.1 因为这里是子路由,所以先遍历,排除没有子路由的路由
    2.2 再遍历子路由,看有没有component(具体的页面),排除没有的
    2.3 将有component的对象里的元素封装为一个主路由(我这里主路由名为Home)的子路由
    2.4 但是现在有个问题,每次路由修改之后我都要发请求,浪费,所以,在store中的页面里定义一个布尔类型的validation,给个默认值false,当请求完成,修改为true,下次就不会发请求,节约性能
    1. router.beforeEach((to, from, next) => {
    2. const validation = store.state.menu.validation;
    3. if (!validation) {
    4. axios.get("/sys/menu/nav", {
    5. headers: {
    6. Authorization: localStorage.getItem("token"),
    7. }
    8. }).then(res => {
    9. // 拿到 menuList
    10. store.commit("setMenuList", res.data.data.nav);
    11. // 拿到用户权限
    12. store.commit("setPermList", res.data.data.permList);
    13. // 动态绑定路由
    14. store.state.menu.menuList.forEach(item => {
    15. if (item.children) {
    16. item.children.forEach(e => {
    17. if (e.component) {
    18. router.addRoute("Home", {
    19. path: e.path,
    20. name: e.name,
    21. component: () => import(`@/views/${e.component}`),
    22. });
    23. }
    24. });
    25. }
    26. });
    27. // 更新 validation 状态
    28. console.log(123456)
    29. store.commit('setValidation', true);
    30. // 确保在异步操作完成后继续导航
    31. next({path: to.fullPath});
    32. }).catch(error => {
    33. console.error('Error fetching menu:', error);
    34. // 处理请求失败的情况,例如重定向到登录页面
    35. next('/login');
    36. });
    37. } else {
    38. // 如果已经验证过,直接继续导航
    39. next();
    40. }
    41. });

  • 相关阅读:
    Kubernetes技术与架构(七)
    Trie字典树
    pinctrl
    AST 初探深浅,代码还能这样玩?
    驱动 | Linux | NVMe - 1. 内核驱动
    linux Shell入门
    YOLOv8-Seg改进:渐近特征金字塔网络(AFPN)
    深度学习与CV教程(12) | 目标检测 (两阶段,R-CNN系列)
    神经网络参数个数计算,神经网络的参数设置
    SELinux,无semanage,Linux user到SELinux user的映射
  • 原文地址:https://blog.csdn.net/qq_55121347/article/details/141059128