问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何用addRoutes实现子路由动态添加

发布网友 发布时间:2022-05-14 18:05

我来回答

2个回答

懂视网 时间:2022-05-14 22:26

这篇文章主要介绍了关于addRoutes实现动态权限路由菜单,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

需求

最近接手一个后台管理系统,需要实现导航菜单从后台拉取的效果;根据登录用户的权限不同分别拉出来的导航菜单也不一样,另外可操作的界面也存在区别。

问题

因为后台管理系统是准备使用vue+vue-router+element-ui+vuex的搭配来做的,可是单页应用在进入页面之前就已经将vue-router实例化并且注入vue实例中了,所以在进入登录页面的时候旧没办法在重新定制路由了。接下来各种百之谷之,发现vue-router在2.0版本中提供了addRoutes方法添加路由,希望的曙光出现。
经过一番折腾终于实现了功能,记录下来便于回顾,也希望能帮助到同样有需求的同志。

思路

1、首先在本地配置好固定不变的路由地址,例如登录,404这些页面,如下:

import Vue from 'vue'
import Router from 'vue-router'
import store from '@/vuex/store'
Vue.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部分,所以需要后端返回给我们包含所有路由的一个数组就可以了

3331747386-5a2109ac94bff_articlex[1].png

返回的数据中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 <= 1) {
  this.$router.addRoutes(routes)
  // this.$router不是响应式的,所以手动将路由元注入路由对象
  this.$router.options.routes.push(routes)
  }
  this.$router.replace('/layout/index')
  }
  })
  .catch((err) => {
  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 < subs.length; i++) {
 let temp = {
  path: subs[i].actUrl,
  name: subs[i].actUrl,
  component: (resolve) => 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
 }
}

至此我们已经将权限路由成功配置进本地路由了,我的系统登录进入如下

4071308234-5a210c0c961eb_articlex[1].png

后续优化

1、菜单列表的显示以及二级导航切换:

<template>
 <p class="mainMenu">
 <el-menu
 class="menubar"
 mode="horizontal"
 :default-active="activeCode"
 background-color="#545c64"
 text-color="#fff"
 active-text-color="#ffd04b">
 <el-menu-item :index="item.code | splitCode" v-for="item in menuList" :key="item.code" @click="switchSubMenu(item)" v-if="item.code !== '0008'">
  <i :class="`iconfont icon-${item.imgUrl}`"></i>
  <span slot="title">{{item.name}}</span>
 </el-menu-item>
 </el-menu>
 </p>
</template>

<script type="text/ecmascript-6">
 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)
 }
 }
 }
</script>

2、防止刷新路由丢失;由于在刷新的时候单页应用会重新初始化,这时候所有配置的路由都会丢失,一朝回到解放前,只有本地配置的路由能够跳转。这时候我们可以在app.vue(ps:不论在哪里进行刷新,app.vue都会执行)中执行如下代码:

<script>
 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)
 }
 }
 }
</script>

这样即使刷新,也会重新配置路由了。
3、关于页面按钮级别控制,可以自定义一个指令,去做这件事情。因为我们已经权限列表放入了相应路由的meta对象中,所以我们可以很方便的在每个页面回去到当前用户在当前页面所拥有的权限

2962255271-5a210efb6248a_articlex[1].png

结语

打完收工,得亏vue-router2中添加了addRoutes的方法

热心网友 时间:2022-05-14 19:34

调用cmroute.dll,快速添加路由表。
注:本法对于一般的pppoe拨号仍有效(win7下电信宽带pppoe拨号测试通过,只不过稍慢因其中一个系统svchost.exe进程占用一会cpu,机制不明)
新建一个文件夹,准备如下文件:
1、cmroute.dll
这个动态连接库,系统中没有的话,可以从网上自行搜索下载,猛击这里也提供下载(整个文件夹)。
2、addroutes.bat
建立批处理文件内容如下(引号中),用于调用cmroute.dll从而快速添加路由表:

echo 正在添加路由表......
rundll32.exe cmroute.dll,SetRoutes /STATIC_FILE_NAME addchnroutes.txt /DONT_REQUIRE_URL /IPHLPAPI_ACCESS_DENIED_OK


3、addchnroutes.txt
建立txt文件,内含路由表信息,上面的批处理调用这个txt文件,格式如下(引号中):
“add 1.0.1.0 mask 255.255.255.0 default METRIC default IF default”

4、delroutes.bat
上面添加的都是活动路由,重启之后即消失。若要立即删除上述路由则建立:
delroutes.bat,内容如下(引号中)

echo 正在删除路由表......
rundll32.exe cmroute.dll,SetRoutes /STATIC_FILE_NAME delchnroutes.txt /DONT_REQUIRE_URL /IPHLPAPI_ACCESS_DENIED_OK


跟上面添加路由的批处理格式完全一样,不同之处在于读取的txt文件不同。
5、delchnroutes.txt
删除路由表批处理读取的txt文件,ip地址、子网掩码跟添加的一样,add换成delete而已,如下(引号中)
“delete 1.0.1.0 mask 255.255.255.0 default METRIC default IF default”
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
若cpu一秒执行n次运算需耗能5w,那执行2n次运算要耗能是大于小于还是等于... 大神们,N5G跟N5W哪里不一样? 刚出生的婴儿会感冒吗 刚出生宝宝感冒的症状 怀庄永佳福代理,什么品牌白酒好呢? 做白酒品牌代理,有怀庄永佳福牌子怎么样? 怀庄永佳福白酒喝得人多吗?代理怎么样? 为什么很多女性都把男闺密当作结婚对象? 关于电影“罗生门”的问题 实际利率法是指什么 泰兴市兴安精细化工有限公司怎么样? 泰兴哪里买美巢腻子粉 泰兴市宏成塑业有限公司怎么样? 泰兴黄桥 营业执照 佛牌金壳银壳防水壳对佛牌功效有影响么 Sea&Sea MDX-5DIII 防水壳 求介绍 防水相机和防水壳哪个好? 手机防水壳是真的能防水吗 西门子PLC计数器问题 傻瓜相机用防水壳可以拍照片吗? 运用字体排版技术制作头像图片的方法 单片机计数器问题 单片机 计数器问题 PLC中计数器的问题 请教一下有图片 边框 标题文字 段文字这几个元素怎么排版更好看,要求扁平化的设计 计数器问题 苹果手机怎样取消按主屏幕解锁? 为什么苹果手机屏幕得按主屏键才能开锁 云顶隐藏聚光灯怎么找 云顶之弈直击弱点对法师有用吗 佳能相机防水壳的市场价格是多少 正常的西瓜种植是几月份 荣耀9忘记数字密码怎么办? 小米电视EA55应用市场好多没有软件 临汾的牛肉丸子面怎么样?生意好吗?一碗面的利润有多大呀? 太原哪儿的临汾牛肉丸子面最正宗? 关于临汾牛肉丸子面的作文 日照特产海中宝鱿鱼怎么吃 取一个抽象一点的网名或笔名 帮我取一个网名‘抽象一点’ 关于日照吃海鲜、买特产,在线等 来个有抽象意义的网名,不要繁体的,也不要搞笑的、哪和网友帮忙,谢谢阿… 灵魂摆渡 白蛇的扮演者 寝室好几个同学都在网上买鱿鱼丝吃,我也想试试,哪种牌子的比较靠谱呢? 需要个简单朴实的网名 , 最好再有点抽象, 呵呵 哪位朋友的知道比较好的... 日照市汇利水产有限公司怎么样? 对灵魂摆渡白蛇故事的评价 公路车码表出现小扳子是什么问题什么问题 带“良”字的网名!可抽象!高悬赏! 灵魂摆渡2中白蛇的扮演者