微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

vue addRoutes实现动态权限路由菜单的示例

需求

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

问题

因为后台管理系统是准备使用vue+vue-router+element-ui+vuex的搭配来做的,可是单页应用在进入页面之前就已经将vue-router实例化并且注入vue实例中了,所以在进入登录页面的时候旧没办法在重新定制路由了。接下来各种百之谷之,发现vue-router在2.0版本中提供了addRoutes方法添加路由,希望的曙光出现。

经过一番折腾终于实现了功能,记录下来便于回顾,也希望能帮助到同样有需求的同志。

思路

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

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、然后重要的一步,我们需要跟后端老铁约定好需要返回的权限菜单列表信息;首先这里我们先分析一下自己需要的路由结构,这里以我自己的路由作为例子。如果是我自己直接定义路由的话,会是以下结构:

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部分,所以需要后端返回给我们包含所有路由的一个数组就可以了

功能,只是作为切换二级菜单的触发器,subList才是我们真正需要的路由信息。

{ 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

rush:js;"> const routes = [ { path: '/',redirect: '/layout' },{ path: '/layout',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`],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、菜单列表的显示以及二级导航切换:

rush:js;">

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

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

rush:js;">

这样即使刷新,也会重新配置路由了。

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

参考官方文档自定义指令

结语

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


可以通过min-width属性来设置el-table-column的最小宽度。以下是一个示例: &lt;template&gt; &lt;el-table :data=&quot;tableData&quot;&gt; &lt;el-table-column prop=&quot;item_no&q
yarn dev,当文件变动后,会自动重启。 yanr start不会自动重启 nodemon会监听文件变动,跟yarn dev和yarn start无关。
ref 用于创建一个对值的响应式引用。这个值可以是原始值(如数字或字符串)或对象。当 ref 的值发生变化时,Vue 会自动更新 DOM 或任何其他使用该 ref 的响应式依赖。 使用示例: import { ref } from &#39;vue&#39;; const count = ref(0
通过修改 getWK005 函数来实现这一点。这里的 query 参数就是发送 GET 请求时的查询参数。你可以将需要的条件作为 query 对象的属性传递进去。比如,如果你想要按照特定的条件查询信息,你可以在调用 getWK005 函数时传递这些条件。例如: getWK005({ conditio
&lt;el-form-item label=&quot;入库类型&quot; prop=&quot;mt_type&quot;&gt; &lt;el-select v-model=&quot;form.mt_type&quot; filterable placeholder=&quot;请选择&q
API 变动 样式类名变化: 一些组件的样式类名有所变动,可能需要更新你的自定义样式。 事件名和属性名变化: 某些组件的事件名和属性名发生了变化,需要检查 Element Plus 文档 以了解详细信息。 使用 setup 函数: 在 Vue 3 中,可以使用 Composition API(如 s
安装和引入方式 Element UI (Vue 2): // main.js import Vue from &#39;vue&#39;; import ElementUI from &#39;element-ui&#39;; import &#39;element-ui/lib/theme-cha
排查400 (Bad Request)和解决这个问题,可以按照以下步骤进行: 检查URL和端点:确保URL http://127.0.0.1:8008/basicApp/BS037HModel/ 是正确的,并且该端点在服务器上存在。 检查请求参数:确认发送请求时的任何参数都是正确的,包括查询参数、请
在 Vue.js 中,&lt;template&gt; 标签是一种特殊的标签,它用于定义组件的模板,但不会直接渲染为 HTML 元素。它的主要用途是在编写组件和使用插槽时提供灵活的模板定义。以下是关于 &lt;template&gt; 标签的一些关键概念和使用示例。 基本用法 组件模板:在单文件组件
el-config-provider是Element Plus库中的一个组件,用于提供全局的配置。它是Element Plus在2.0版本中引入的新组件。 el-config-provider组件的作用是允许你在应用程序中统一配置Element Plus的一些全局属性和样式,这些配置将被应用于所有E