vue点击左侧菜单右侧显示内容 vue有上菜单也有左侧菜单
怎样使用vueaddRoutes实现动态权限路由菜单
阅读:这次给大家带来怎样使用vue addRoutes实现动态权限路由菜单,怎样使用vue addRoutes实现动态权限路由菜单的注意事项有哪些,下面就是实战案例,一起来看一下。
vue点击左侧菜单右侧显示内容 vue有上菜单也有左侧菜单
vue点击左侧菜单右侧显示内容 vue有上菜单也有左侧菜单
vue点击左侧菜单右侧显示内容 vue有上菜单也有左侧菜单
需求
近接手一个后台管理系统,需要实现导航菜单从后台拉取的效果;根据登录用户的权限不同分别拉出来的导航菜单也不一样,另外可作的界面也存在区别。
问题
因为后台管理系统是准备使用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)
routes: [
{path: '/login',
name: 'login',
meta: {requireAuth: false},
// 模块使用异步加载
component: (resolve) => require(['../components/login/login.vue'], resolve)
}]
})
// 拦截登录,token验证
router.beforeEach((to, from, next) => {
if === undefined) {
if (store.state.token) {
next()
} else {
next({
path: '/login'
})
}} else {
next()
}})
export default router配置好这些固定的路由后我们才能够到登录页面,不然是无法继续下去的。
2、然后重要的一步,我们需要跟后端老铁约定好需要返回的权限菜单列表信息;首先这里我们先分析一下自己需要的路由结构,这里以我自己的路由作为例子。如果是我自己直接定义路由的话,会是以下结构:
routes: [
{path: '/login',
name: 'login',
meta: {requireAuth: false},
component: (resolve) => require(['../components/login/login.vue'], resolve)
},
{path: '/',
redirect: '/layout'
},
component: (resolve) => require(['../layout.vue'], resolve),
children: [
{path: 'index',
meta: {
type: '1', //控制是否显示隐藏 1显示,2隐藏
code: 00010001, // 后面需要控制路由高亮
title: '首页', // 菜单名称
permissonList: [] // 权限列表
},
{...
}]
}]
})根据以上结构分析,其实真正需要动态配置的路由其实是/layout下面的children部分,所以需要后端返回给我们包含所有路由的一个数组就可以了
返回的数据中rootList中是一级导航的列表,一级导航实际是没有路由功能,只是作为切换二级菜单的触发器,subList才是我们真正需要的路由信息。
3、拿到权限路由信息后,需要我们在本地对数据进行处理组装成我们需要的数据:
// 登录
login () {
let params = {
account: this.loginForm.username,
password: encrypt(this.loginForm.password)
this.$.t(this.$bumng + '/login', this.$HP(params))
.then((res) => {
this.loging = false
console.('菜单列表:', res)
if (res.resultCode === this.$state_ok) {
// 合并一级菜单和二级菜单,便于显示
let menus = res.subList)
this.seRes({label: 'menuList', value: menus})
// 根据subList处理路由
let routes = 本地化subList,便于在刷新页面的时候重新配置路由
this.seRes({label: 'subList', value: res.subList})
// 防止重复配置相同路由
if (this.$router.options.routes.length <= 1) {
this.$router.addRoutes(routes)
// this.$router不是响应式的,所以手动将路由元注入路由对象
this.$router.options.routes.push(routes)
}})
.catch((err) => {
this.loging = false
console.e}this.$router.replace('/layout/index')rror('错误:', err)
})
},处理菜单列表和subList的方法:mergeSubInRoot 和 mergeRoutes
const routes = [
{path: '/',
redirect: '/layout'
},
component: (resolve) => require(['../layout.vue'], resolve),
children: []
}]
/
合并主菜单和子菜单
@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: routes [Array] 本地路由列表
/
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]ponent}.vue`], resolve),
meta: {
type: subs[i].type,
code: subs[i].code,
permissionList: subs[i].permissionList
routes[1].children.push(temp)
return routes
}}至此我们已经将权限路由成功配置进本地路由了,我的系统登录进入如下
后续优化
1、菜单列表的显示以及二级导航切换:
mode="horizontal" :default-active="activeCode" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b"> {{.name}}
import {mapState, mapMutations} from 'vuex'
name: 'menu',
data () {
msg: 'Welcome to Your Vue.js App'
comd: {
...mapState(['menuList']),
activeCode () {
// 通过code保证在切换字路由的情况下一级路由也是高亮显示
return 4)
mods: {
...mapMutations(['seRes']),
// 切换二级路由
switchSubMenu (route) {
console.('路由:', route)
if (route.actUrl !== 'index') {
// 用currentSubMenu控制二级路由数据
this.seRes({label: 'currentSubMenu', value: route.children})
this.$router.小伙伴们首先可能想到的是watch$route,但是在这我不使用watch,因为watch如果用户刷新页面的情况下,会兼听不到。我们用的是 window.location.pathnamepush(`/layout/${route.children[0].actUrl}`)
} else {
// 不存在二级路由隐藏二级
this.seRes({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'
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 = this.$router不是响应式的,所以手动将路由元注入路由对象
this.$router.options.routes.push(routes)
}这样即使刷新,也会重新配置路由了。
3、关于页面按钮级别控制,可以自定义一个指令,去做这件事情。因为我们已经权限列表放入了相应路由的meta对象中,所以我们可以很方便的在每个页面回去到当前用户在当前页面所拥有的权限
相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!
使用create-react-app构建React开发环境步奏详解
如何使用element-ui 限制日期选择
vue-antd-admin框架(二) 布局与页面渲染
上文中提到在App.vue文件中使用了router-view来展示路由对modalOFF:应的视图,针对router-view,解释如下,有兴趣的童鞋移步 链接
在此之前,我们要了解该框架下几个重要的布局组件:
我们以默认的路由/#/dashboard/workplace 为例,看下页面如何展示对应组件。
框架中如果没有设置使用异步路由,默认路由在router/config.js中,dashboard配置的路由如下
如上,访问根路径会被重定向到#/login,登录成功后会重定向到/#/dashboard/workplace。
路由匹配:1)根路径 2)/dashboard路径 3)/dashboard/workplace
路由匹配到根路径,并加载TabsView组件到App.vue中指定的router-view中,我们来看下TabsView组件。
它位于@layouts/TabsView.vue中,主要有AdminLayout包裹contextmenu(右键菜单)、tabsHead(多tab标签栏)以及下级路由渲染的router-view组成。
整个页面的展示如下
dashboard匹配加载BlankView,BlankView是一个空白页面,主要包含切换动画和router-view
还有另外一种PageView,包含了 PageLayout 布局和路由视图内容区
展示如下
在workplace组件中,主要使用antd组件库中的 Grid布局
以上为vue-antd-admin框架的布局和渲染流程,接下来剖析左侧菜单以资产及路由解析规则的生成