51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Vue-Router根据用户权限添加动态路由(侧边栏菜单)

动态路由

如果你的网页有管理员、普通用户等多种角色类型,不同的角色能看到的页面/菜单应该是不同的,所以不同的用户登录之后应该监听到不同的动态路由和渲染不同的菜单,这个时候就需要用到动态路由。

简单来说就是根据用户信息获取其对应的权限,生成对应的路由挂载,然后动态渲染有权限的菜单于侧边栏菜单。

实现思路图示:

来自掘金:小绿与小蓝

使用到的路由方法:https://router.vuejs.org/zh/api/index.html#addroute

image-20221101221146642

实现步骤

1、定义静态路由(包括登录、公用页面)、动态路由,且初始化时只挂载静态路由。

import { createRouter, createWebHashHistory } from 'vue-router'; //1.按需导入需要的方法
import Main from '../views/Main.vue';
const router = createRouter({
  //3.创建路由对象
  history: createWebHashHistory(), //3.1指定通过hash管理路由的切换
  routes: [
    //3.2创建路由规则
      //静态路由
    {
      path: '/',
      component: Main,
      name: 'Home',
      redirect: '/home',
      children: [
          //这里放公共的组件
        {
          path: '/user/usercenter',
          name: 'usercenter',
          component: () => import('../views/User/UserCenter.vue'),
        },
      ],
    },
    {
      path: '/login',
      name: 'login',
      component: () => import('../views/Login.vue'),
    },
  ],
});

export default router; //4.向外共享路由对象

2、用户登录成功,根据权限拿到数据并做持久化保存。

//登录的处理方法-main.js
const login = async () => {
      const res = await proxy.$api.getMenu(loginForm);
      // console.log(res);
      // 将获取到的菜单值传给store
      store.commit('setMenu', res.menu);
      // 动态添加路由菜单
      store.commit('addMenu', router);
    //获取的Token值存储
      store.commit('setToken', res.token);
      router.push({
        name: 'home',
      });
      ElMessage({
        message: '登录成功',
        type: 'success',
      });
    };

3、将数据处理之后使用addRoute方法添加到子路由。

因为这里的menuArray是作为home的二级路由添加的,所以在方法中指定home就能将menuArray添加为home的子路由。

    // 登录后获取到的菜单持久化保存
    setMenu(state, val) {
      state.menu = val;
      localStorage.setItem('menu', JSON.stringify(val));
    },
    // 添加路由菜单
    addMenu(state, router) {
      // 有无存储的菜单值判断
      if (!localStorage.getItem('menu')) {
        return;
      }
      // 如果有,将菜单值保存
      const menu = JSON.parse(localStorage.getItem('menu'));
      state.menu = menu;
      const menuArray = [];
      //3.处理数据
      menu.forEach((item) => {
        //如果存在子路由则将子路由保存
        if (item.children) {
          item.children = item.children.map((item) => {
            let url = `../views/${item.url}.vue`;
            item.component = modules[url];
            return item;
          });
            //添加到menuArray数组的children中
          menuArray.push(...item.children);
        } else {
          let url = `../views/${item.url}.vue`;
          item.component = modules[url];
            //添加到menuArray数组中
          menuArray.push(item);
        }
      });
        //添加生成的新菜单数组到路由
      menuArray.forEach((item) => {
        // 使用router.addRoute动态添加为Home的子路由
        router.addRoute('Home', item);
      });
    },

踩炕注意

刷新动态路由消失

页面刷新后,会造成动态路由消失,原因是因为在addRoute方法中:

提示

请注意,添加路由并不会触发新的导航。也就是说,除非触发新的导航,否则不会显示所添加的路由。

解决方案

在渲染之前直接添加

store.commit('addMenu', router);

app.use(router).use(store);
app.mount('#app');

路由懒加载

先简单介绍一些路由懒加载:

传统的写法:

//先导入组件
import Main from '../views/Main.vue';

//然后定义路由规则
routes: [
    { path: '/main',
      component: Main,
    },  
]

懒加载写法:

//直接写路由规则
routes: [
    { path: '/main',
      component: () => import('../views/Main.vue'),
    },  
]

懒加载就是按需去加载路由对应的资源,提高首屏加载速度,代码实现也很简单,但大大的提升了响应速度。

但是我在vite3中使用时,动态加载模板字符串的组件时报错,可以使用vite提供的Glob 导入。

它匹配到的文件默认也是懒加载的,具体解决方案看这篇文章:

Vue3和vite项目踩炕提示The above dynamic import cannot be analyzed by Vite.

赞(3)
未经允许不得转载:工具盒子 » Vue-Router根据用户权限添加动态路由(侧边栏菜单)