web前端|js教程
单页应用,vue-router,vue.js
web前端-js教程
这篇文章主要介绍了关于addRoutes实现动态权限路由菜单,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下
自动采集文章论坛源码,vscode怎样多行编辑,ubuntu 编译暂停,查询tomcat内存占用,安卓sqlite自动更新,多台服务器分布式爬虫,webmin php,网店seo搜索优化引擎,织梦企业黄页网站源码,地方旅游网站模板lzw
需求
jsp的网上书店源码,能运行vscode的平板,Ubuntu开机多久,jsp怎么发到tomcat,爬虫 中美贸易,php 字符串拼接方法,蚌埠seo网络推广哪里靠谱,旅游网站安装及使用说明,88号令模板lzw
最近接手一个后台管理系统,需要实现导航菜单从后台拉取的效果;根据登录用户的权限不同分别拉出来的导航菜单也不一样,另外可操作的界面也存在区别。
婚车网站源码,ubuntu删除ip地址,安装tomcat9服务,爬虫淘宝价钱,php小测验,seo网站公司介绍内容重要性lzw
问题
因为后台管理系统是准备使用vue+vue-router+element-ui+vuex的搭配来做的,可是单页应用在进入页面之前就已经将vue-router实例化并且注入vue实例中了,所以在进入登录页面的时候旧没办法在重新定制路由了。接下来各种百之谷之,发现vue-router在2.0版本中提供了addRoutes方法添加路由,希望的曙光出现。
经过一番折腾终于实现了功能,记录下来便于回顾,也希望能帮助到同样有需求的同志。
思路
1、首先在本地配置好固定不变的路由地址,例如登录,404这些页面,如下:
import Vue from vueimport Router from vue-routerimport store from @/vuex/storeVue.use(Router)let router = new Router({ routes: [ {path: /login,name: login,meta: {requireAuth: false},// 模块使用异步加载component: (resolve) => require([../components/login/login.vue], resolve) }]})// 拦截登录,token验证router.beforeEach((to, from, next) => { if (to.meta.requireAuth === undefined) { if (store.state.token) {next() } else {next({ path: /login}) } } else { next() }})export default router
配置好这些固定的路由后我们才能够到登录页面,不然是无法继续下去的。
2、然后重要的一步,我们需要跟后端老铁约定好需要返回的权限菜单列表信息;首先这里我们先分析一下自己需要的路由结构,这里以我自己的路由作为例子。如果是我自己直接定义路由的话,会是以下结构:
let router = new Router({ routes: [ {path: /login,name: login,meta: {requireAuth: false},component: (resolve) => require([../components/login/login.vue], resolve) }, { path: /, redirect: /layout }, { path: /layout, component: (resolve) => require([../layout.vue], resolve), children: [ {path: index, meta: { type: 1, //控制是否显示隐藏 1显示,2隐藏 code: 00010001, // 后面需要控制路由高亮 title: 首页, // 菜单名称 permissonList: [] // 权限列表}component: (resolve) => require([@/components/index/index.vue], resolve) }, { ... } ] }]})
根据以上结构分析,其实真正需要动态配置的路由其实是/layout下面的children部分,所以需要后端返回给我们包含所有路由的一个数组就可以了
返回的数据中rootList中是一级导航的列表,一级导航实际是没有路由功能,只是作为切换二级菜单的触发器,subList才是我们真正需要的路由信息。
3、拿到权限路由信息后,需要我们在本地对数据进行处理组装成我们需要的数据:
// 登录login () { let params = {account: this.loginForm.username,password: encrypt(this.loginForm.password) } this.loading = true this.$http.post(this.$bumng + /login, this.$HP(params)).then((res) => { this.loging = false console.info(菜单列表:, res) if (res.resultCode === this.$state_ok) { // 合并一级菜单和二级菜单,便于显示 let menus = handleMenu.mergeSubInRoot(res.rootList, res.subList) // 本地化处理好的菜单列表 this.saveRes({label: menuList, value: menus}) // 根据subList处理路由 let routes = handleMenu.mergeRoutes(res.subList) // 本地化subList,便于在刷新页面的时候重新配置路由 this.saveRes({label: subList, value: res.subList}) // 防止重复配置相同路由 if (this.$router.options.routes.length { this.loging = false console.error(错误:, err)})},
处理菜单列表和subList的方法:mergeSubInRoot 和 mergeRoutes
const routes = [ { path: /, redirect: /layout }, { path: /layout, component: (resolve) => require([../layout.vue], resolve), children: [] }]export default { /** * 合并主菜单和子菜单 * @param: rootList [Array] 主菜单列表 * @param: subList [Array] 子菜单 * */ mergeSubInRoot (roots, subs) { if (roots && subs) {for (let i = 0; i < roots.length; i++) { let rootCode = roots[i].code roots[i].children = [] for (let j = 0; j < subs.length; j++) {if (rootCode === subs[j].code.substring(0, 4)) { roots[i].children.push(subs[j])} }} } return roots }, /** * 合并远程路由到本地路由 * @param: subList [Array] 远程路由列表 * @param: routes [Array] 本地路由列表 * */ mergeRoutes (subs) { if (subs) {for (let i = 0; i require([`@/components/${subs[i].component}.vue`], resolve),meta: { type: subs[i].type, code: subs[i].code, title: subs[i].name, permissionList: subs[i].permissionList} } routes[1].children.push(temp)} } return routes }}
至此我们已经将权限路由成功配置进本地路由了,我的系统登录进入如下
后续优化
1、菜单列表的显示以及二级导航切换:
{{item.name}}
import {mapState, mapMutations} from vuex export default { name: menu, data () {return { msg: Welcome to Your Vue.js App} }, computed: {...mapState([menuList]),activeCode () {// 通过code保证在切换字路由的情况下一级路由也是高亮显示 return this.$route.meta.code.substring(0, 4)} }, methods: {...mapMutations([saveRes]),// 切换二级路由switchSubMenu (route) { console.info(路由:, route) if (route.actUrl !== index) {// 用currentSubMenu控制二级路由数据 this.saveRes({label: currentSubMenu, value: route.children})this.$router.push(`/layout/${route.children[0].actUrl}`) } else {// 不存在二级路由隐藏二级 this.saveRes({label: currentSubMenu, value: \})this.$router.push(`/layout/${route.actUrl}`) }} }, filters: {splitCode (code) { return code.substring(0, 4)} } }
2、防止刷新路由丢失;由于在刷新的时候单页应用会重新初始化,这时候所有配置的路由都会丢失,一朝回到解放前,只有本地配置的路由能够跳转。这时候我们可以在app.vue(ps:不论在哪里进行刷新,app.vue都会执行)中执行如下代码:
import {decrypt} from @/libs/AES import handleMenu from @/router/handleMenu export default { name: app, created () {// 当this.$router.options.routes的长度为1,且本地缓存存在菜单列表的时候才重新配置路由if (this.$router.options.routes.length <= 1 && sessionStorage.getItem(subList)) { let subList = JSON.parse(decrypt(sessionStorage.getItem(subList))) let routes = handleMenu.mergeRoutes(subList) this.$router.addRoutes(routes) // this.$router不是响应式的,所以手动将路由元注入路由对象 this.$router.options.routes.push(routes)} } }
这样即使刷新,也会重新配置路由了。
3、关于页面按钮级别控制,可以自定义一个指令,去做这件事情。因为我们已经权限列表放入了相应路由的meta对象中,所以我们可以很方便的在每个页面回去到当前用户在当前页面所拥有的权限
结语
打完收工,得亏vue-router2中添加了addRoutes的方法