1.配制pinia定义token
store/user.js
import { defineStore } from 'pinia'
import { ref } from 'vue'
// 用户模块
export const useUserStore = defineStore(
'big-user',`在这里插入代码片`
() => {
const token = ref('') // 定义 token
const setToken = (t) => (token.value = t) // 设置 token
return { token, setToken }
},
{
persist: true // 持久化
}
)
2.封装axios模块
新建utils/request.js
import axios from "axios";
import router from "@/router";
import { ElMessage } from "element-plus";
import { useUserStore } from "@/stores/user";
const baseURL = 'http://big-event-vue-api-t.itheima.net' //请求地址
const instance = axios.create({
// TODO 1.基础地址 超时时间
baseURL,
timeout: 100000
})
//请求拦截
instance.interceptors.request.use(
//config 请求拦截器的一个参数
//能拿到请求的一些信息,参数,请求头之类
(config) => {
// TODO 2.携带token
const userStore = useUserStore()
if(userStore.token){
//通过设置config.headers.Authorization来传递身份验证信息
config.headers.Authorization = userStore.token
}
return config
},
(err) => Promise.reject(err)
)
//响应拦截
instance.interceptors.response.use(
(res) => {
// TODO 3.处理业务失败
// TODO 4.摘取核心响应数据
//res.data 即为后端服务器返回的数据
//res.data.code === 0 通常用来检查HTTP响应的状态码是否为0。在很多后端系统中
//0通常表示请求成功,而非0的代码则表示出现了某种错误。
if( res.data.code === 0){
return res
}
ElMessage({ message:res.data.message || '服务异常', type: 'error'})
return Promise.reject(res.data)
},
(err) => {
// TODO 5.处理401错误
ElMessage({message: err.response.data.message || '服务异常', type: 'error' })
console.log(err);
if(err.response?.status === 401) {
//后端返回401,就说明没登录 没token或者token已经过期
router.push('/login')
}
return Promise.reject(err)
}
)
export default instance
export {baseURL}
3.新建types文件夹定义数据类型
types/params
根据接口文档
//声明数据类型
// 注册校验数据类型
export type UserRegisterParamsType = {
username: string
password: string
repassword: string
}
4.封装api接口
api/user.js
注册接口
记得引入request以及声明的数据类型
import request from '@/utils/request'
import type {
UserRegisterParamsType,
UserLoginParamsType
} from '@/types/params'
// 调用注册接口
export const userRegisterService = (params:UserRegisterParamsType) => {
const { username, password, repassword } = params
return request.post('/api/reg', { username, password, repassword })
}
5.注册按钮点击事件
//注册之前进行校验 调用接口
const register = async () => {
await reform.value.validate()
console.log('开始注册请求');
await userRegisterService(registerForm.value)
ElMessage.success('注册成功')
//切换到登录页
isRegister.value = false
}
6.登录接口数据类型声明
//登录校验数据类型
export type UserLoginParamsType = {
username: string
password: string
}
7.调用登录接口
// 调用登录接口
export const userloginService = (params: UserLoginParamsType ) => {
const { username, password } = params
return request.post('/api/login', { username, password })
}
8.登录按钮点击事件
//调用方法将token存入pinia并自动持久化到本地
const userStore = useUserStore()
//调用路由
const router = useRouter()
//登录之前进行校验 调用接口
const login = async () => {
await form.value.validate()
console.log('开始登录');
const res = await userloginService(loginForm.value)
console.log(res)
console.log(res.data.token);
userStore.setToken(res.data.token)
ElMessage.success('登录成功')
router.push('/')
}
9.登录访问拦截
//前置路由导航
//登录访问拦截 => 默认直接放行
//根据返回值绝定是放行还是拦截
//返回值:
//1.undefined / true 直接放行
//2.false拦回from的地址页面
//3.具体路劲 或 路径对象 拦截到对应地址
// '/login' { name: 'login'}
//在beforeEach函数中,参数传递的"to"表示将要访问的路径
router.beforeEach((to) => {
//判断有无token 且访问的是非登录页 拦截到登录 其他情况正常放行
// || 二选一
// && 都要
const useStore = useUserStore()
if (!useStore.token && to.path !== '/login') {
return '/login'
} else {
return true
}
})