vue vue-router vuex操作权限
这次给大家带来vue vue-router vuex操作权限,vue vue-router vuex操作权限的注意事项有哪些,下面就是实战案例,一起来看一下。
基于vuex, vue-router,vuex的权限控制教程,完整代码地址见 https://github.com/linrunzheng/vue-permission-control
接下来让我们模拟一个普通用户打开网站的过程,一步一步的走完整个流程。
首先从打开本地的服务localhost:8080开始,我们知道打开后会进入login页面,那么判断的依据是什么。
首先是token。
没有登陆的用户是获取不到token的,而登陆后的角色我们会将token存到local或者seesionStorage 因此,根据当前有没有token即可知道是否登陆。
为了存取token并且方便我们操作,可以配和vuex实现
/* state.js */ export default { get UserToken() { return localStorage.getItem('token') }, set UserToken(value) { localStorage.setItem('token', value) } } /* mutation.js */ export default { LOGIN_IN(state, token) { state.UserToken = token }, LOGIN_OUT(state) { state.UserToken = '' } }
拦截的判断
没有token进入需要权限的页面:redirect到login页面
由于我们路由是动态挂载的,包括 ' ' 和404,所以当匹配不到路由时,也重定向到login
router.beforeEach((to, from, next) => { if (!store.state.UserToken) { if ( to.matched.length > 0 && !to.matched.some(record => record.meta.requiresAuth) ) { next() } else { next({ path: '/login' }) } } })
好了,此时用户打开localhost:8080,默认匹配的是''路径,此时我们并没有挂载路由,也没有token,所以来到了login。
输入用户名密码后,有token了,通过store触发* commit('LOGIN_IN')* 来设置token。
但是还是没有路由,目前最开始只有login路由
/* 初始路由 */ export default new Router({ routes: [ { path: '/login', component: Login } ] }) /* 准备动态添加的路由 */ export const DynamicRoutes = [ { path: '', component: Layout, name: 'container', redirect: 'home', meta: { requiresAuth: true, name: '首页' }, children: [ { path: 'home', component: Home, name: 'home', meta: { name: '首页' } } ] }, { path: '/403', component: Forbidden }, { path: '*', component: NotFound } ]
我们要根据当前用户的token去后台获取权限。
由于权限这块逻辑还挺多,所以在vuex添加了一个permission模块来处理权限。
为了判断是已有路由列表,需要在vuex的permission模块存一个state状态permissionList用来判断,假如permissionList不为null,即已经有路由,如果不存在,就需要我们干活了。
router.beforeEach((to, from, next) => { if (!store.state.UserToken) { ... } else { /* 现在有token了 */ if (!store.state.permission.permissionList) { /* 如果没有permissionList,真正的工作开始了 */ store.dispatch('permission/FETCH_PERMISSION').then(() => { next({ path: to.path }) }) } else { if (to.path !== '/login') { next() } else { next(from.fullPath) } } } })
来看一下 store.dispatch('permission/FETCH_PERMISSION') 都干了什么
actions: { async FETCH_PERMISSION({ commit, state }) { /* 获取后台给的权限数组 */ let permissionList = await fetchPermission() /* 根据后台权限跟我们定义好的权限对比,筛选出对应的路由并加入到path=''的children */ let routes = recursionRouter(permissionList, dynamicRouter) let MainContainer = DynamicRoutes.find(v => v.path === '') let children = MainContainer.children children.push(...routes) /* 生成左侧导航菜单 */ commit('SET_MENU', children) setDefaultRoute([MainContainer]) /* 初始路由 */ let initialRoutes = router.options.routes /* 动态添加路由 */ router.addRoutes(DynamicRoutes) /* 完整的路由表 */ commit('SET_PERMISSION', [...initialRoutes, ...DynamicRoutes]) } }
首先,await fetchPermission()获取后台给的权限数组,格式大概如下
{ "code": 0, "message": "获取权限成功", "data": [ { "name": "订单管理", "children": [ { "name": "订单列表" }, { "name": "生产管理", "children": [ { "name": "生产列表" } ] }, { "name": "退货管理" } ] } ] }
其次根据我们写好的路由数组,进行对比,过滤得到我们要的路由
/* 这里是我们写好的需要权限判断的路由 */ const dynamicRoutes = [ { path: '/order', component: Order, name: 'order-manage', meta: { name: '订单管理' }, children: [ { path: 'list', name: 'order-list', component: OrderList, meta: { name: '订单列表' } }, { path: 'product', name: 'product-manage', component: ProductManage, meta: { name: '生产管理' }, children: [ { path: 'list', name: 'product-list', component: ProductionList, meta: { name: '生产列表' } }, { path: 'review', name: 'review-manage', component: ReviewManage, meta: { name: '审核管理' } } ] }, { path: 'returnGoods', name: 'return-goods', component: ReturnGoods, meta: { name: '退货管理' } } ] } ] export default dynamicRoutes
为了对比,我写好了一个递归函数,用name和meta.name进行对比 ,根据这个函数就可以得到我们想要的结果
/** * * @param {Array} userRouter 后台返回的用户权限json * @param {Array} allRouter 前端配置好的所有动态路由的集合 * @return {Array} realRoutes 过滤后的路由 */ export function recursionRouter(userRouter = [], allRouter = []) { var realRoutes = [] allRouter.forEach((v, i) => { userRouter.forEach((item, index) => { if (item.name === v.meta.name) { if (item.children && item.children.length > 0) { v.children = recursionRouter(item.children, v.children) } realRoutes.push(v) } }) }) return realRoutes }
得到过滤后的数组后,加入到path为''的children下面
{ path: '', component: Layout, name: 'container', redirect: 'home', meta: { requiresAuth: true, name: '首页' }, children: [ { path: 'home', component: Home, name: 'home', meta: { name: '首页' } }, <!-- 将上面得到的东西加入到这里 --> ... ] }
这个时候,path为''的children就是我们左侧的导航菜单了,存到state的sidebarMenu待用。加入到children后,这时DynamicRoutes就可以加入到路由了。
/* 动态添加路由 */ router.addRoutes(DynamicRoutes) /* 初始路由 */ let initialRoutes = router.options.routes /* 合并起来,就是完整的路由了 */ commit('SET_PERMISSION', [...initialRoutes, ...DynamicRoutes])
路由添加完了,也就是action操作完毕了,即可在action.then里面调用 next({ path: to.path })进去路由,这里要注意, next里面要传参数即要进入的页面的路由信息,因为next传参数后,当前要进入的路由会被废止,转而进入参数对应的路由,虽然是同一个路由,这么做主要是为了确保addRoutes生效了。
进入路由后,要开始生成左侧菜单,之前我们已经存到sidebarMenu了,现在需要做的只是递归生成菜单而已,虽然用了element的导航菜单,但是为了递归路由,还需要自己封装一下。这里核心的地方是组件的name,在组件里面有children的地方,又再次使用自己,从而遍历整个tree结构的路由。
<template> <p class="menu-container"> <template v-for="v in menuList"> <el-submenu :index="v.name" v-if="v.children&&v.children.length>0" :key="v.name"> <template slot="title"> <i class="iconfont icon-home"></i> <span>{{v.meta.name}}</span> </template> <el-menu-item-group> <my-nav :menuList="v.children"></my-nav> </el-menu-item-group> </el-submenu> <el-menu-item :key="v.name" :index="v.name" @click="gotoRoute(v.name)" v-else> <i class="iconfont icon-home"></i> <span slot="title">{{v.meta.name}}</span> </el-menu-item> </template> </p> </template> <script> export default { name: 'my-nav', props: { menuList: { type: Array, default: function() { return [] } } }, methods: { gotoRoute(name) { this.$router.push({ name }) } } } </script>
刷新页面后,根据我们router.beforeEach的判断,有token但是没permissionList,我们是会重新触发action去获取路由的,所以无需担心。但是导航菜单active效果会不见。不过我们已经把el-menu-item的key设置为路由的name,那么我们只要在刷新后,在afterEach把当前路由的name赋值给el-menu default-active即可。同理,在afterEach阶段获取所有matched的路由,即可实现面包屑导航。
if (!store.state.permission.permissionList) { store.dispatch('permission/FETCH_PERMISSION').then(() => { next({ path: to.path }) }) } ... router.afterEach((to, from, next) => { var routerList = to.matched store.commit('setCrumbList', routerList) store.commit('permission/SET_CURRENT_MENU', to.name) })
退出登陆后,需要刷新页面,因为我们是通过addRoutes添加的,router没有deleteRoutes这个api,所以清除token,清除permissionList等信息,刷新页面是最保险的。
最后还有一点,每次请求得带上token, 可以对axios封装一下来处理
var instance = axios.create({ timeout: 30000, baseURL }) // 添加请求拦截器 instance.interceptors.request.use( function(config) { // 请求头添加token if (store.state.UserToken) { config.headers.Authorization = store.state.UserToken } return config }, function(error) { return Promise.reject(error) } ) /* axios请求二次封装 */ instance.get = function(url, data, options) { return new Promise((resolve, reject) => { axios .get(url, data, options) .then( res => { var response = res.data if (response.code === 0) { resolve(response.data) } else { Message.warning(response.message) /* reject(response.message) */ } }, error => { if (error.response.status === 401) { Message.warning({ message: '登陆超时,请重新登录' }) store.commit('LOGIN_OUT') window.location.reload() } else { Message.error({ message: '系统异常' }) } reject(error) } ) .catch(e => { console.log(e) }) }) } export default instance
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上是vue vue-router vuex操作权限的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

可以让用户对系统进行更深入的操作和定制,root权限是一种管理员权限,在Android系统中。获取root权限通常需要一系列繁琐的步骤,对于普通用户来说可能不太友好、然而。通过一键开启root权限,本文将介绍一种简单而有效的方法,帮助用户轻松获取系统权限。了解root权限的重要性及风险拥有更大的自由度,root权限可以让用户完全控制手机系统。加强安全控制等,定制主题、用户可以删除预装应用。比如误删系统文件导致系统崩溃,过度使用root权限也存在风险、不慎安装恶意软件等,然而。在使用root权限前

PyCharm是一款非常流行的Python集成开发环境(IDE),它提供了丰富的功能和工具,使得Python开发变得更加高效和便捷。本文将为大家介绍PyCharm的基本操作方法,并提供具体的代码示例,帮助读者快速入门并熟练操作该工具。1.下载和安装PyCharm首先,我们需要前往PyCharm官网(https://www.jetbrains.com/pyc

sudo(超级用户执行)是Linux和Unix系统中的一个关键命令,允许普通用户以root权限运行特定命令。sudo的功能主要体现在以下几个方面:提供权限控制:sudo通过授权用户以临时方式获取超级用户权限,从而实现了对系统资源和敏感操作的严格控制。普通用户只能在需要时通过sudo获得临时的特权,而不需要一直以超级用户身份登录。提升安全性:通过使用sudo,可以避免在常规操作中使用root账户。使用root账户进行所有操作可能会导致意外的系统损坏,因为任何错误或不小心的操作都将具有完全的权限。而

qq空间如何设置权限访问?在QQ空间中是可以设置权限访问,但是多数的小伙伴不知道QQ空间如何设置权限访问的功能,接下来就是小编为用户带来的qq空间设置权限访问方法图文教程,感兴趣的用户快来一起看看吧!QQ使用教程qq空间如何设置权限访问1、首先打开QQ应用,主页面点击左上角【头像】点击;2、然后左侧展开个人信息专区,点击左下角【设置】功能;3、进入到设置页面滑动,找到其中的【隐私】选项;4、接下来在隐私的界面,其中的【权限设置】服务;5、之后挑战到最新页面选择【空间动态】;6、再次在QQ空间设置

LinuxDeploy的操作步骤及注意事项LinuxDeploy是一款强大的工具,可以帮助用户在Android设备上快速部署各种Linux发行版,让用户能够在移动设备上体验到完整的Linux系统。本文将详细介绍LinuxDeploy的操作步骤以及注意事项,同时提供具体的代码示例,帮助读者更好地使用这一工具。操作步骤:安装LinuxDeploy:首先在

想必很多的用户家里都有那么几台不用的电脑,因为长时间不用完全忘记了开机密码,于是想要知道一下,忘记密码要怎么操作呢?那就一起来看看吧。win10开机密码忘记按F2怎么操作1、按下电脑的电源键,然后开机时按下F2(不同电脑品牌进入bios的按键也不同)。2、在bios界面中,找到security选项(不同品牌电脑的位置可能有所不同)。一般都在顶部的设置菜单中。3、然后找到SupervisorPassword选项并且点击。4、这时候用户就可以看到自己的密码了,同时找到旁边的Enabled切换为Dis

随着智能手机的普及,截屏功能成为日常使用手机的必备技能之一。华为Mate60Pro作为华为公司的旗舰手机之一,其截屏功能自然也备受用户关注。今天,我们就来分享华为Mate60Pro手机的截屏操作步骤,让大家能够更加便捷地进行截屏操作。首先,华为Mate60Pro手机提供了多种截屏方式,可以根据个人习惯选择适合自己的方式进行操作。下面详细介绍几种常用的截

Discuz论坛权限管理:阅读权限设置指南在Discuz论坛管理中,权限设置是至关重要的一环。其中,阅读权限的设置尤为重要,它决定了不同用户在论坛中能够看到的内容范围。本文将详细介绍Discuz论坛的阅读权限设置,以及如何针对不同的需求进行灵活的配置。一、阅读权限基础概念在Discuz论坛中,阅读权限主要有以下几个概念需要了解:默认阅读权限:新用户注册后默认
