概述
首先我们来谈谈如何生成动态路由的问题,我在处理这个问题的时候也是折腾了两天才确定了最终的解决方案,下面我来讲述下中间过程。
刚开始的时候我的基本思路是在登录后调用后台获取菜单列表的接口然后添加到路由里面去,同时把菜单数据存到store里面,在进入首页之后从store里取出来生成左侧菜单列表。然而,当我把代码写完之后,发现当页面刷新时候,页面就空白了。经过分析后,这个的根本原因是没有做路由的持久化,而且页面刷新之后store里面的数据也清空了。为了解决上述问题,我就在登录后获取到的菜单数据列表存在localstorage里,貌似这样确实可以解决问题,后来想一想如果这样操作的话那人家就突破权限的控制去直接修改localstorage里面的菜单数据了,肯定不安全,接下来我就讲述一下正确的思路。
我们在路由导航beforeEach钩子函数里,即进入页面之前做处理,当token存在的时候,并且路由不存在时(这个条件一定要有,防止重复调用接口)来调用菜单接口,获取到菜单数据后存到store里方便页面左侧菜单从store里监听和获取,同时把数据通过addRoutes()方法添加到动态路由里面。这样就能保证每次进入页面或者刷新页面后从后台能拿到数据并且动态添加到路由里面,store里的菜单数据每次都能保存进来。
这里要注意一点,后台给的component字段是个string类型的,那怎么能够替换成我们真实的组件呢?其实也简单,运用递归算法,遍历出来替换成真实组件就ok了。因为后台给的菜单可能是一级菜单,可能是一级菜单下还有二级菜单,二级菜单下可能有三级菜单,这种数据嵌套的场景就要用递归算法来解决了。下面我附上代码,供大家参考。
main.js
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import './assets/iconfont/iconfont.css'
import 'v-charts/lib/style.css'
import VCharts from 'v-charts'
import App from './App.vue'
import router from './router/index'
import routeList from './router/routes'
import store from './store'
import './js/directives'
import request from './js/request'
Vue.use(ElementUI, { size: 'small', zIndex: 3000 })
Vue.use(VCharts)
Vue.config.productionTip = false
Vue.prototype.$post = request.post
Vue.prototype.$get = request.get
Vue.prototype.$delete = request.delete
Vue.prototype.$formData = request.formData
Vue.prototype.$download = request.download
Vue.prototype.$put = request.put
Vue.prototype.$formDataType2 = request.formDataType2
const filterRoutes = res => {
for (let i = 0; i < res.length; i++) {
if (res[i].component) {
res[i].component = routeList[res[i].component]
if (res[i].children) {
filterRoutes(res[i].children)
}
}
}
return res
}
const getRoutes = () => {
const username = JSON.parse(localStorage.getItem('USER')).username
request.get(`menu/${username}`).then(res => {
if (res) {
store.commit('common/setMenuList', res[0].children)
res[0].children.push({ name: '项目设置', path: '/projectSet/:id', component: 'ProjectSet', hidden: true })
router.addRoutes(filterRoutes(res))
}
})
}
router.beforeEach((to, from, next) => {
if (to.path === '/login') {
next()
} else {
if (localStorage.getItem('USER_TOKEN')) {
!to.name && getRoutes()
next()
} else {
next('/login')
}
}
})
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
路由模块:
附上后台给的菜单数据代码:
{
"success": true,
"data": [{
"path": "/",
"name": "主页",
"component": "Index",
"icon": "none",
"redirect": "/home",
"children": [{
"path": "/home",
"name": "系统首页",
"component": "Home",
"icon": "iconfont icon-shouye",
"meta": {
"closeable": true
}
}, {
"path": "/projects",
"name": "项目管理",
"component": "ProjectsHome",
"icon": "iconfont icon-xiangmuguanli",
"meta": {
"closeable": true
}
}, {
"path": "/monitor",
"name": "系统监控",
"component": "Monitor",
"icon": "iconfont icon-xitongjiankong",
"meta": {
"closeable": true
},
"children": [{
"path": "/monitor/onlineUser",
"name": "在线用户",
"component": "OnlineUser",
"icon": "iconfont icon-zaixianyonghu",
"meta": {
"closeable": true
}
}, {
"path": "/monitor/sysLogs",
"name": "系统日志",
"component": "SysLogs",
"icon": "iconfont icon-xitongrizhi",
"meta": {
"closeable": true
}
}, {
"path": "/monitor/redisInfo",
"name": "Redis监控",
"component": "RedisInfo",
"icon": "iconfont icon-Redisjiankong",
"meta": {
"closeable": true
}
}, {
"path": "/monitor/requestTrack",
"name": "请求追踪",
"component": "RequestTrack",
"icon": "iconfont icon-qingqiuzhuizong",
"meta": {
"closeable": true
}
}, {
"path": "/monitor/sysInfo",
"name": "系统信息",
"component": "SysInfo",
"icon": "iconfont icon-xitongxinxi",
"meta": {
"closeable": true
},
"children": [{
"path": "/monitor/sysInfo/jvmInfo",
"name": "JVM信息",
"component": "JvmInfo",
"icon": "iconfont icon-JVMxinxifuwuqixinxi",
"meta": {
"closeable": true
}
}, {
"path": "/monitor/sysInfo/serverInfo",
"name": "服务器信息",
"component": "ServerInfo",
"icon": "iconfont icon-fuwuqixinxi",
"meta": {
"closeable": true
}
}]
}]
}, {
"path": "/system",
"name": "系统管理",
"component": "System",
"icon": "iconfont icon-xitongguanli",
"meta": {
"closeable": true
},
"children": [{
"path": "/system/role",
"name": "角色管理",
"component": "Role",
"icon": "iconfont icon-jiaoseguanli1",
"meta": {
"closeable": true
}
}, {
"path": "/system/menu",
"name": "菜单管理",
"component": "Menu",
"icon": "iconfont icon-caidanguanli1",
"meta": {
"closeable": true
}
}, {
"path": "/system/user",
"name": "用户管理",
"component": "User",
"icon": "iconfont icon-yonghuguanli1",
"meta": {
"closeable": true
}
}, {
"path": "/system/dept",
"name": "部门管理",
"component": "Dept",
"icon": "iconfont icon-bumenguanli",
"meta": {
"closeable": true
}
}, {
"path": "/system/dict",
"name": "字典管理",
"component": "Dict",
"icon": "iconfont icon-zidianguanli",
"meta": {
"closeable": true
}
}]
}, {
"path": "/userInfo",
"name": "个人中心",
"component": "UserInfo",
"icon": "iconfont icon-gerenzhongxin",
"meta": {
"closeable": true
}
}]
}, {
"path": "*",
"name": "error",
"redirect": "/404"
}]
}
至此,动态路由的问题我们已经解决了,下面我们来解决下按钮权限控制的问题。
我这里的思路是,登录后后台返回所有有权限的字段,附上代码:
["user:view", "role:update", "dept:add", "role:add", "dict:add", "role:export", "menu:update", "menu:export", "dict:view", "dict:update", "dept:export", "menu:view", "role:view", "dept:delete", "user:export", "role:delete", "dept:view", "menu:delete", "project:operate", "user:add", "user:delete", "log:view", "user:kickout", "user:update", "dict:delete", "dept:update", "menu:add", "log:delete", "redis:view", "log:export", "user:reset", "dict:export", "user:online"]
这个数据我把它存在本地localstorage,方便全局使用,这里不可能在每个按钮的页面来写方法判断是否有权限,所以我采用vue的全局指令的方法来进行控制,附上代码:
import Vue from 'vue'
const permissions = JSON.parse(localStorage.getItem('PERMISSIONS'))
// 权限指令
Vue.directive('hasPermission', {
bind (el, binding) {
if (!permissions.includes(binding.value)) {
el.style.display = 'none'
}
}
})
如何使用,我这里就举个例子:
<el-button v-hasPermission="'dept:delete'" @click="handleDel">删除</el-button>
至此,根据后台返回的菜单数据动态生成路由和按钮权限控制问题解决。
最后
以上就是会撒娇音响为你收集整理的vue element 动态生成多选选项_vue里面动态路由的生成,和按钮权限的控制经验分享...的全部内容,希望文章能够帮你解决vue element 动态生成多选选项_vue里面动态路由的生成,和按钮权限的控制经验分享...所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复