基于vue,vue

网友投稿 288 2023-02-06


基于vue,vue

基于vuex, vue-router,vuex的权限控制教程,完整代码地址见 https://github.com/linrunzheng/vue-permission-control

接下来让我们模拟一个普通用户打开网站的过程,一步一步的走完整个流程。

首先从打开本地的服务localhost:8080开始,我们知道打开后会进入login页面,那么判断的依据是什么。

首先是toke

n。

没有登陆的用户是获取不到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: '首页'

},

chilhttp://dren: [

{

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": "订单管理",mnnwGmyjn

"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结构的路由。

{{v.meta.name}}

{{v.meta.name}}

刷新页面后,根据我们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) {http://

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

总结

以上所述是给大家介绍的基于vue,vue-router, vuex及addRoutes进行权限控制问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,会及时回复大家的。在此也非常感谢大家对我们网站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring Boot利用@Async异步调用:使用Future及定义超时详解
下一篇:详解Spring Cloud 断路器集群监控(Turbine)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~