当前位置:网站首页>如何实现后台管理系统的权限路由和权限菜单

如何实现后台管理系统的权限路由和权限菜单

2020-11-09 18:09:09 InfoQ

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"前言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文是继 实战的最后一篇文章, 主要介绍"},{"type":"text","marks":[{"type":"strong"}],"text":"如何实现后台管理系统的权限路由和权限菜单"},{"type":"text","text":". 希望通过这3篇文章的复盘和实战, 可以让大家开发企业应用的时候更加游刃有余."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文主要涉及的技术点如下:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如何使用"},{"type":"text","marks":[{"type":"strong"}],"text":"递归算法"},{"type":"text","text":"动态渲染不定层级的菜单"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如何基于权限来控制菜单展现"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基于"},{"type":"text","marks":[{"type":"strong"}],"text":"nodejs"},{"type":"text","text":"的权限服务设计"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"正文"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"动态菜单和权限路由是后台管理系统设计中必不可少的环节, 作为复杂后台管理系统来说, 导航菜单往往不是简单的一级菜单, 往往都会有3级,4级菜单, 如下:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d7/d7cc6fe11a7c0593f6a0de42d7163c52.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以我们首要解决的问题就是面对"},{"type":"text","marks":[{"type":"strong"}],"text":"未知层级菜单"},{"type":"text","text":"时的前端解决方案. 其次就是面对不同角色,需要展示不同的权限菜单, 我们如何解决这两个问题, 是实现权限菜单的第一步,接下来笔者就会带大家一起实现."}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"使用递归算法动态渲染不定层级的菜单"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先我们来解决第一个问题, 实现渲染不定层级的菜单. 我们目前常用的菜单schema如下:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"const menuData = [\n {\n key: '/manage',\n path: '/manage',\n text: 'dooring工作台',\n },\n {\n key: '/manage/anazly',\n path: '/manage/anazly',\n text: '数据大盘',\n },\n {\n key: '/manage/h5',\n text: 'H5服务中心',\n sub: [\n {\n key: '/manage/h5/config',\n path: '/manage/h5/config',\n text: 'H5页面管理',\n },\n {\n key: '/manage/h5/tpl',\n path: '/manage/h5/tpl',\n text: '模板库',\n }\n ]\n },\n {\n key: '/manage/order',\n path: '/manage/order',\n text: '订单管理',\n }\n]\n复制代码"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们可以通过实现一个js算法来遍历这个数据生成动态菜单, 比如for, 递归等, 笔者这里采用递归来实现, 关于菜单组件的选择, 我们可以使用"},{"type":"text","marks":[{"type":"strong"}],"text":"antd"},{"type":"text","text":"的"},{"type":"text","marks":[{"type":"strong"}],"text":"Menu"},{"type":"text","text":", 也可以使用"},{"type":"text","marks":[{"type":"strong"}],"text":"element UI"},{"type":"text","text":", "},{"type":"text","marks":[{"type":"strong"}],"text":"iView"},{"type":"text","text":"等, 原理基本一致, 这里笔者直接写出我的"},{"type":"text","marks":[{"type":"strong"}],"text":"javascript"},{"type":"text","text":"递归版本:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"const { SubMenu } = Menu;\nconst createMenu = (menu = []) => {\n return menu.map(item => {\n if(item.sub) {\n return \n { createMenu(item.sub) }\n \n }else {\n return \n { item.text }\n \n }\n })\n }\n复制代码"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通过以上方式我们就可以渲染出任何层级的菜单了, 在"},{"type":"text","marks":[{"type":"strong"}],"text":"H5-Dooring"},{"type":"text","text":"后台中效果如下:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/97/97dc232a2562c7655a2d444bb852f292.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果没有权限需求, 大家可以直接用以上方案实现任何动态层级菜单. 接下来我们来实现具有权限功能的动态菜单."}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"基于权限来控制菜单展现"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在上面的实现中我们已经实现了动态层级菜单, 对于有权限管理功能的系统, 我们需要对不同用户展现不同菜单, 比如"},{"type":"text","marks":[{"type":"strong"}],"text":"超级管理员"},{"type":"text","text":", "},{"type":"text","marks":[{"type":"strong"}],"text":"普通管理员"},{"type":"text","text":", 或者更细的划分, 我们需要在遍历菜单的时候去动态根据权限过滤, 接下来我们看一个例子:超级管理员登录的菜单界面:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/88/88c424e12378480440d2265599c75826.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"普通管理员登录的菜单界面:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/69/6913be4a3905a94b2bd86fda0dbf7e9e.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先要想实现权限菜单, 我们需要修改菜单schema结构, 添加权限字段,如下:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"const menuData = [\n {\n key: '/manage',\n path: '/manage',\n text: 'dooring工作台'\n },\n {\n key: '/manage/anazly',\n path: '/manage/anazly',\n text: '数据大盘',\n },\n {\n key: '/manage/auth',\n path: '/manage/auth',\n text: '会员管理',\n auth: true,\n },\n {\n key: '/manage/h5',\n text: 'H5服务中心',\n sub: [\n {\n key: '/manage/h5/config',\n path: '/manage/h5/config',\n text: 'H5页面管理',\n },\n {\n key: '/manage/h5/tpl',\n path: '/manage/h5/tpl',\n text: '模板库',\n auth: true,\n }\n ]\n }\n]\n复制代码"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上图可知我们添加了"},{"type":"text","marks":[{"type":"strong"}],"text":"auth"},{"type":"text","text":"字段作为权限标示, 这里我们主要用"},{"type":"text","marks":[{"type":"strong"}],"text":"true"},{"type":"text","text":"和"},{"type":"text","marks":[{"type":"strong"}],"text":"false"},{"type":"text","text":"表示, 因为这里只有2中角色, 如果有多种权限, 我们可以用特殊字符串或者数字表示, 这块只需要和后端约定好即可. 具体实现如下:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"const createMenu = (menu = []) => {\n return menu.map(item => {\n if(item.sub) {\n return \n { createMenu(item.sub) }\n \n }else {\n if((rp === 'super' && item.auth) || !item.auth) {\n return \n { item.text }\n \n }else {\n return null\n }\n }\n })\n }\n复制代码"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上就实现了动态不限层级的"},{"type":"text","marks":[{"type":"strong"}],"text":"权限菜单"},{"type":"text","text":". 大家可以直接食用哈~"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"基于nodejs的权限服务设计"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上实现主要是前端层面的设计方案, 我们都知道前端的安全措施永远是不可靠的, 所以我们为了保证系统的安全性, 一般我们会把菜单数据存到后端, 通过接口动态请求权限菜单. 这块我们可以提前和后端做好约定, 让后端根据不同用户返回不同的权限菜单"},{"type":"text","marks":[{"type":"strong"}],"text":"schema"},{"type":"text","text":"即可. 由于方案比较简单, 这里笔者就不一一介绍了. 感兴趣可以在参考"},{"type":"text","marks":[{"type":"strong"}],"text":"H5-Dooring"},{"type":"text","text":"的实现."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"所以, 今天你又博学了吗?"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"最后"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上教程笔者已经集成到"},{"type":"link","attrs":{"href":"https://github.com/MrXujiang/h5-Dooring","title":null},"content":[{"type":"text","text":"H5-Dooring"}]},{"type":"text","text":"中,对于一些更复杂的交互功能,通过合理的设计也是可以实现的,大家可以自行探索研究。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"github地址:"},{"type":"link","attrs":{"href":"https://github.com/MrXujiang/h5-Dooring","title":null},"content":[{"type":"text","text":"H5编辑器H5-Dooring"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"开源投票入口:"},{"type":"link","attrs":{"href":"https://www.oschina.net/p/h5-dooring","title":null},"content":[{"type":"text","text":"为H5-Dooring投票"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果想学习更多H5游戏, "},{"type":"text","marks":[{"type":"strong"}],"text":"webpack"},{"type":"text","text":","},{"type":"text","marks":[{"type":"strong"}],"text":"node"},{"type":"text","text":","},{"type":"text","marks":[{"type":"strong"}],"text":"gulp"},{"type":"text","text":","},{"type":"text","marks":[{"type":"strong"}],"text":"css3"},{"type":"text","text":","},{"type":"text","marks":[{"type":"strong"}],"text":"javascript"},{"type":"text","text":","},{"type":"text","marks":[{"type":"strong"}],"text":"nodeJS"},{"type":"text","text":","},{"type":"text","marks":[{"type":"strong"}],"text":"canvas"},{"type":"text","text":"数据可视化等前端知识和实战,欢迎在《趣谈前端》一起学习讨论,共同探索前端的边界。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}

版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://xie.infoq.cn/article/903bf1a288027a35eca2b7c7c?utm_source=rss&utm_medium=article