因为项目需要依据后端返回条件动态显示路由,通宵研究了一整个晚上搞出来的比较简单的实现方式
原理
antdPro用的是umi的路由,大体的实现方式是这样的:
router.config.js => .umi/router.js => models/menu.js <=> layouts/BasicLayout.js => components/SiderMenu/index.js
PS: 这仅是针对menuData流向做的分析图 (这里是最终的左边栏)
事实上menu.js依据开发者写在router.config.js里的路径算出来要显示的内容,在这里稍微解释一下:
effects: {
*getMenuData({ payload }, { put }) {
const { routes, authority } = payload;
const menuData = filterMenuData(memoizeOneFormatter(routes, authority));
const breadcrumbNameMap = memoizeOneGetBreadcrumbNameMap(menuData);
yield put({
type: 'save',
payload: { menuData, breadcrumbNameMap },
});
},
},
上面是menu.js的内容,意图是将取到的routes(路由实体)和authority(权限配置)交给 memoizeOneFormatter 这个函数,变成未经处理的menuData(包含了所有可见和不可见路由的路由数组) 再交给 filterMenuData 这个函数去计算出真正用于显示的menuData,下面是这部分代码
可以看到 filterMenuData 先是筛掉了要隐藏的目录,然后依据父目录的子目录做了递归,再整理成目录结构的数组最后返回成需要的menuData,这就是最后用于显示的menuData,所以说,我们可以进行干预的部分就是替换掉 memoizeOneFormatter 这个函数的效果,直接把我们算好的初步menuData交给 filterMenuData 之后这个函数就会自己生成我们需要的用于显示的目录
PS:之所以在这一步替换是因为umi路由实际上除了计算实体路由之外,还分开记录了目录对应的key值来实现动画效果,如果有兴趣可以去研究一下源码,如果直接替换menuData本身,会因为缺少必要的数据而无法正确存储对应的key值,直接体现就是四处报错。。。我也是思考了很久才决定在这里处理数据
实现
我在这里写一个demo
我的办法是自己写了一个数组 ss 扔进 filterMenuData 然后页面就显示了这个模拟出的正确路由,当然至于这个ss只是个demo,开发正常应该是后端扔给前端权限name,前端在验证登录的时候同样去递归这个数据得到类似于我写的ss这样的结构,这样就完成了动态路由的显示
本文也参考了以下的文章
https://www.yuque.com/liuyin-zzwa0/ada6ao/va6p77
转载请标明出处哦~