首页 web前端 js教程 vue vue-router vuex操作权限

vue vue-router vuex操作权限

May 14, 2018 pm 01:58 PM
操作 权限

这次给大家带来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中文网其它相关文章!

推荐阅读:

react router4+redux控制路由权限步骤详解

v-bind与v-on使用案例详解

Vue表单类父子组件数据传递数据方法总结

以上是vue vue-router vuex操作权限的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

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

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

一键开启root权限(快速获取root权限) 一键开启root权限(快速获取root权限) Jun 02, 2024 pm 05:32 PM

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

PyCharm使用教程:详细指引你运行操作 PyCharm使用教程:详细指引你运行操作 Feb 26, 2024 pm 05:51 PM

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

什么是 sudo,为什么它如此重要? 什么是 sudo,为什么它如此重要? Feb 21, 2024 pm 07:01 PM

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

qq空间如何设置权限访问 qq空间如何设置权限访问 Feb 23, 2024 pm 02:22 PM

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

Linux Deploy的操作步骤及注意事项 Linux Deploy的操作步骤及注意事项 Mar 14, 2024 pm 03:03 PM

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

win10开机密码忘记按F2怎么操作 win10开机密码忘记按F2怎么操作 Feb 28, 2024 am 08:31 AM

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

华为Mate60 Pro截屏操作步骤分享 华为Mate60 Pro截屏操作步骤分享 Mar 23, 2024 am 11:15 AM

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

Discuz论坛权限管理:阅读权限设置指南 Discuz论坛权限管理:阅读权限设置指南 Mar 10, 2024 pm 05:33 PM

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

See all articles