【项目配置】6-router-permission结合ts封装
发表于:2023-09-15 |

前言

本文基于之前的项目配置代码进行讲解

路由拦截定义

路由拦截是指在路由跳转前,对路由进行拦截,判断是否有权限进行跳转,如果没有权限则跳转到指定页面,如果有权限则跳转到目标页面。常用于需要登录的系统中,如果没有登录则跳转到登录页面,如果已经登录则跳转到目标页面。

路由拦截的实现

src下新建permission.ts文件

导入路由并且监听操作路由跳转前的行为

1
2
3
4
import router from '@/router';
router.beforeEach(async (to,from,next)=>{
console.log(to,from,next)
})

main.ts下引入permission.ts

1
import './permission';

查看页面效果

路由拦截
此时我们可以看到我们的页面并没有进行渲染,而是一直在打印路由信息,通过to,和from就可以得到我们是从哪个路由跳转到哪个路由的了,因为我们没有进行next()操作,所以路由一直处于拦截状态,我们可以在permission.ts中添加next()操作

permission.ts添加next()操作

1
2
3
4
5
import router from '@/router';
router.beforeEach(async (to,from,next)=>{
console.log(to,from,next)
next()
})

此时我们可以看到页面已经渲染出来了
路由放行

permission.ts添加权限判断

基于上面这个逻辑,我们就可以实现最简单的权限判断了,我们可以在permission.ts中添加权限判断逻辑,如果有权限则next(),如果没有权限则跳转到指定页面

login.vue

在pages下面新建login文件夹,再新建一个index.vue,随便搞点代码

1
2
3
4
5
<template>
<div>
我是登录页面
</div>
</template>

路由添加

修改router文件夹下的index.ts中的这部分代码,把login加上

1
2
3
4
5
6
7
8
9
10
11
12
// 其他固定路由
const defaultRouterList: Array<RouteRecordRaw> = [
{
path: '/login',
name: 'login',
component: () => import('@/pages/login/index.vue'),
},
{
path: '/',
redirect: '/home',
},
];

因为我们之前都没给我们的home和about路由加上name,现在记得加上,在router文件下的modules文件夹下的homepage.ts中加上name

1
2
3
4
5
6
7
8
9
10
11
12
export default [
{
path:"/home",
component:()=>import("@/pages/home/index.vue"),
name:"home",
},
{
path:"/about",
component:()=>import("@/pages/about/index.vue"),
name:"about",
}
]

store中添加token属性

往store文件夹下的modules中的user.ts中添加token属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { defineStore } from 'pinia';
import { store } from '@/store';

export const useUserStore= defineStore('user', {
state: () => ({
username: '',
token: 'main_token',
isAdmin: false,
}),
actions: {
setValue(param: { username: string; isAdmin: boolean }) {
this.username = param.username;
this.isAdmin = param.isAdmin;
},
},
persist: false,
});

export function getUserStore() {
return useUserStore(store);
}

permission.ts

判断是否有token,如果有token则就进入下一步,判断如果是前往登录界面,那么就放行next(),然后判断路由是否有name,没有的话前往我们的/,如果是有name就是我们自定义的路由,就跳转过去,然后使用try,catch中的catch兜底,如果有错误重定向登录界面,如果没有token则重定向到登录页面
注意:
这段代码在没有token的时候也要添加,不然就会造成死循环,我们重定向到登录页面,但是登录页面又会重定向到登录页面,就会造成死循环

1
2
3
4
if (to.path === '/login') {
next();
return;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import router from '@/router';
import { useUserStore } from '@/store';
router.beforeEach(async (to,from,next)=>{
// console.log(to,from,next)
const userStore = useUserStore();
if (userStore.token) {
if (to.path === '/login') {
next();
return;
}
try {
if (router.hasRoute(to.name)) {
next();
} else {
next(`/`);
}
} catch (error) {
next({
path: '/login',
query: { redirect: encodeURIComponent(to.fullPath) },
});
}
} else {
if (to.path === '/login') {
next();
return;
}
next({
path: '/login',
query: { redirect: encodeURIComponent(to.fullPath) },
});
}
})

ok,此时我们可以看到,因为有token,我们的路由已经跳转到了home页面
路由跳转

去除token

我们可以在store中把token去除之后,我们就被重定向到了登录界面
路由重定向

到这里,最简单的路由拦截操作就讲解完成了,接下来我们进阶一点

白名单路由

白名单路由是指在路由拦截中,有一些路由是不需要进行权限判断的,比如登录页面,注册页面,忘记密码页面等等,这些页面都是不需要进行权限判断的,我们可以把这些路由放在白名单中,当路由跳转到白名单中的路由时,就不需要进行权限判断了,直接放行即可
就相当于当我们没有token的时候原来的

1
2
3
4
if (to.path === '/login') {
next();
return;
}

需要改成

1
2
3
if (whiteListRouters.includes(to.path)) {
next();
}

定义store中的whiteListRouters

新建store下的modules中的permission.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { defineStore } from 'pinia';
import { store } from '@/store';

export const usePermissionStore = defineStore('permission', {
state: () => ({
whiteListRouters: ['/login','/about'],
}),
actions: {

},
});

export function getPermissionStore() {
return usePermissionStore(store);
}

在store.ts中引入

1
2
3
4
5
6
7
8
9
10
11
12
import { createPinia } from 'pinia';
import { createPersistedState } from 'pinia-plugin-persistedstate';

const store = createPinia();
store.use(createPersistedState());

export { store };

export * from './modules/user';
export * from './modules/permission';

export default store;

在permission.ts中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import router from '@/router';
import { useUserStore } from '@/store';
import { getPermissionStore } from '@/store';
router.beforeEach(async (to,from,next)=>{
// console.log(to,from,next)
const userStore = useUserStore();
const permissionStore = getPermissionStore();
const { whiteListRouters } = permissionStore;
if (userStore.token) {
if (to.path === '/login') {
next();
return;
}
try {
if (router.hasRoute(to.name)) {
next();
} else {
next(`/`);
}
} catch (error) {
next({
path: '/login',
query: { redirect: encodeURIComponent(to.fullPath) },
});
}
} else {
if (whiteListRouters.includes(to.path)) {
next();
return;
}
next({
path: '/login',
query: { redirect: encodeURIComponent(to.fullPath) },
});
}
})

此时我们即使在没有token的情况下,也可以跳转到about页面了
白名单

上一篇:
【项目配置】7-tdesign使用
下一篇:
【可视化学习】44-元宇宙基础学习(三)