geeker admin 动态路由

0 环境

1 文档

geeker admin官方文档

element-plus官方文档

vue router官方文档

2 前言

在登录事件中有两个重点关注点:await initDynamicRouter()router.push(HOME_URL) 。前一个是添加动态路由,一般是从后端获取数据,然后通过initDynamicRouter() ,生成动态路由。当然你的项目全是静态路由,去掉 initDynamicRouter() 即可。这里的 router.push(HOME_URL) 是在它跳转前会再次被路由拦截的。下面的内容介绍的是动态路由,已经理解的朋友,可以不用往下看了。

3 动态加载路由(initDynamicRouter)

找到src/views/login/components/LoginForm.vue ,搜索login方法 ,懒的搜索的,可以定位到76行那个位置。进入initDynamicRouter(),核心代码如下:

1 清楚获取菜单列表 && 按钮权限列表的过程

先看initDynamicRouter ,首先这里的PROT1 单独抽出来的前缀,它对应的是/geeker,也就是mock的模拟数据,若是你想用自己的后端,改PROT1 就行,方便我们修改。authStore.getAuthMenuListauthStore.getAuthButtonList ,点进去会发现两个http get请求, 分别是 /menu/list/auth/buttons ,先定位到src/assets/mock/geeker/ ,分别找到menu/list.jsonauth/buttons.json

js 复制代码
// 获取菜单列表
export const getAuthMenuListApi = () => {
  return http.get<Menu.MenuOptions[]>(PORT1 + `/menu/list`, {}, { loading: false });
  // 如果想让菜单变为本地数据,注释上一行代码,并引入本地 authMenuList.json 数据
  return authMenuList;
};

// 获取按钮权限
export const getAuthButtonListApi = () => {
  return http.get<Login.ResAuthButtons>(PORT1 + `/auth/buttons`, {}, { loading: false });
  // 如果想让按钮权限变为本地数据,注释上一行代码,并引入本地 authButtonList.json 数据
  return authButtonList;
};

先看menu/list.json 。如下图所示:代码实在太长了,我精简了一下,这里先获取header里的x-access-token,然后进行判断token的判断,假如判断通过了,返回数组对象。这里重点是数组对象,仔细看这两个对象,第一个对象没有children,而第二个对象中有children,它里面有嵌套路由对象。

它的意义在哪里,先登录进入到首页,会看到侧边栏,如下图我标记的两个位置。当然它也是加载路由的原材料,这里先有个概念,之后会详细说明的。

这里 auth/buttons.json比较简单,不同token,对应着不同的按钮权限。

json 复制代码
{
  "code": 200,
  "data": function({
    _req
  }) {
    let header = _req.header;
    if (header['x-access-token'] === 'bqddxxwqmfncffacvbpkuxvwvqrhln') {
      return {
        "useProTable": ["add", "batchAdd", "export", "batchDelete", "status"],
        "authButton": ["add", "edit", "delete", "import", "export"]
      }
    }
    if (header['x-access-token'] === 'unufvdotdqxuzfbdygovfmsbftlvbn') {
      return {
        "useProTable": ["add", "batchDelete"],
        "authButton": ["add", "edit", "delete", "import", "export"]
      }
    }
  },
  "msg": "成功"
}

2 判断当前用户有没有菜单权限

这里的 authStore.authMenuListGet 是拿到menu/list.json 里的return里的返回值。结合下图和authMenuListGet: state => state.authMenuList

若是菜单权限列表为空,给它个提示,并且清空token,跳到登录页,并且返回了promise,注意了:initDynamicRouter方法里是有异常捕获处理和promise抛出的。中断login后续的操作,不过我看作者也没有用catch捕获它,有其他操作的,可以自行捕获。

3 添加动态路由

有菜单权限列表了,然后就可以添加动态路由了,authStore.flatMenuListGetgetFlatMenuList方法authMenuList 里的数组里每个对象以及它里面有的有children的,全部转成一维数组菜单。方法如下:getFlatMenuList() 先是深拷贝了,然后利用flatMap(flatmap ---> [[{xxx}], [{xxx},{xxx}]] --> [{xxx}....{xxx}])遇到有children的递归 + 展开,将最终的结果展开成一维数组。

js 复制代码
interface MenuOptions {
  path: string;
  name: string;
  component?: string | (() => Promise<unknown>);
  redirect?: string;
  meta: MetaProps;
  children?: MenuOptions[];
}

export function getFlatMenuList(menuList: Menu.MenuOptions[]): Menu.MenuOptions[] {
  let newMenuList: Menu.MenuOptions[] = JSON.parse(JSON.stringify(menuList));
  return newMenuList.flatMap(item => [item, ...(item.children ? getFlatMenuList(item.children) : [])]);
}

如下图:由于菜单权限列表是一维数组了,所以children就不需要了,有则删之。然后就是item.component 的拼接(这里借助import.meta.glob ),回忆一下router静态路由里的component组件 是不是很像,其实就是它老。若是全屏,就直接加入到路由中,否则添加到layout中。

layout 效果图如下。至于它和侧边栏如何配合使用的,等后续有缘的。

4 流程图

流程图

5 总结

主要是为了得到菜单权限列表和加载组件到路由中去,以达到动态的效果。很多细节的判断啥的,不理解无妨,大概知道做了啥就行,毕竟这里基本是固定的。

相关推荐
前端Hardy1 小时前
Wails v3 正式发布:用 Go 写桌面应用,体积仅 12MB,性能飙升 40%!
前端·javascript·go
Highcharts.js1 小时前
Highcharts React v4 迁移指南(下):分步代码示例与常见问题解决
javascript·react.js·typescript·react·highcharts·代码示例·v4迁移
Laurence1 小时前
Qt 前后端通信(QWebChannel Js / C++ 互操作):原理、示例、步骤解说
前端·javascript·c++·后端·交互·qwebchannel·互操作
Pu_Nine_91 小时前
JavaScript 字符串与数组核心方法详解
前端·javascript·ecmascript
这是个栗子2 小时前
前端开发中的常用工具函数(六)
javascript·every
kyriewen2 小时前
异步编程:从“回调地狱”到“async/await”的救赎之路
前端·javascript·面试
前端Hardy2 小时前
别再手动写 loading 了!封装一个自动防重提交的 Hook
前端·javascript·vue.js
前端Hardy2 小时前
前端如何实现“无感刷新”Token?90% 的人都做错了
前端·javascript·vue.js
SuperEugene2 小时前
Vue Router 实战规范:path/name/meta 配置 + 动态 / 嵌套路由,统一团队标准|状态管理与路由规范篇
开发语言·前端·javascript·vue.js·前端框架
小彭努力中3 小时前
194.Vue3 + OpenLayers 实战:动态位置 + 高度 + 角度,模拟卫星地面覆盖范围
前端·css·vue.js·openlayers·animate