Skip to content

Vue3 动态路由

我们开发后台管理系统过程中,会由不同的人操作系统,如admin(一般管理员)superAdmin(超管),及各种运营、财务人员。为了区别这些人员权限,可能会给不同的人分配不一样的角色来展示不同的菜单,这就必须要通过动态路由来实现。下面就来介绍 vue 实现动态路由,需要的朋友可参考一下~

1、登录获取路由 json 数据

login 页面登录,接口返回路由链表(json 数据,父子嵌套形式的),使用 vuex 的异步方法(action)将接口返回的菜单 json 数据(res.data.menuList)存储起来,之后,进行 router 页面跳转(方便大家查看,我这里做了单一层级的菜单+二级菜单

ts
<script setup lang='ts'>
    import { Login } from '@/api/user'
    const submit = ()=> {
        Login({
            username:'米白小站',
            password:'mibaixiaozhan'
        }).then(res => {
            // //接口返回的数据格式,大概是这个样子
            // menuList: [
            //     {//这是一个页面(不含子级)
            //         "title": "菜单管理",
            //         "path": "/role",
            //         "file":"/role.vue"
            //     },
            //     {//这是一个模块
            //         name: "商品管理",
            //         path: "/goods",
            //         children: [
            //             {//这是模块下面的页面
            //                 name: "商品管理模块A页面",
            //                 path: "goods_a",
            //                 route: "/goods/goods_a.vue"
            //             },
            //             ...
            //         ]
            //     }
            // ]
            store.dispatch('ACTION_SET_MENUS',res.data.menuList)
            router.push('/goods_a')
        })
    }
</script>

2、添加至 router

在路由文件(router/index.ts)内,将接口返回的 menuList 添加至 router 后,调用 next()方法进行跳转即可

在处理路由 beforeEach 函数的时候,切记,第一步先判断当前页是否为 login 页面

我这里的判断为:

1、 判断当前页是否为 login

2、 是否存在 token

3、 是否加载过路由链表

在确认没有加载过路由链表的时候,调用routerDadaFunc处理路由 json 方法,重置加载状态后,进行页面跳转

ts
const getToken = true; //是否存在token
var isF = false; //判断动态路由是否已经被获取到了

router.beforeEach(async (to, from) => {
  if (to.path == "/login") {
    return true;
  }
  if (!getToken) {
    return { path: "/login" };
  } else {
    if (isF) {
      return true;
    } else {
      let add = store.state.resRoute || "";
      routerDadaFunc(add);
      isF = true;
      return { ...to, replace: true };
    }
  }
});

3、递归处理路由链表

方法说明:此方式使用的是动态拼接静态路由中的 import 加载,然后递归调用,addRoute 添加路由。这种方式简化了使用 name 匹配,接口数据 for 循环套着静态路由 for 循环判断匹配。按照此逻辑搭建好之后,前端只需要新建对应目录的模块/页面组件.vue,完全不用处理路由相关代码,接口返回了一个模块 A,前端对应目录有 A 模块.vue 文件就可以(页尾留有 demo 源码获取方式)

ts
const routerData = (result: any) => {
  let currenRoutes = router.options.routes as any;
  if (result) {
    result.forEach((item: any) => {
      // has用于判断当前路由中是否已经具有,避免重复
      var has = currenRoutes.some((it) => it.path == item.path);
      if (!has) {
        currenRoutes.push({
          path: `${item.path}`,
          name: item.title,
          meta: {
            title: item.title,
          },
          component: () => import(`../pages${item.file}`),
        });
        router.addRoute("home", {
          path: `${item.path}`,
          name: item.title,
          meta: {
            title: item.title,
          },
          component: () => import(`../pages${item.file}`),
        });
      }
      if (item.children && item.children.length) {
        routerData(item.children);
      }
    });
  }
};

点击登录之后,页面就是这个样子的了

扫码联系我,获取demo源码

描述文字