Pinia管理用户数据
基本思想:Pinia负责用户数据相关的state和action,组件中只负责触发action函数并传递参数
步骤1:创建userStore
1-创建store/userStore.js
import { loginAPI } from '@/apis/user'
export const useUserStore = defineStore('user', () => {
// 1. 定义管理用户数据的state
const userInfo = ref({})
// 2. 定义获取接口数据的action函数
const getUserInfo = async (user) => {
const res = await loginAPI(user)
userInfo.value = res.result
}
// 3. 以对象的格式把state和action return
return {
userInfo,
getUserInfo,
}
})
2-重构login.vue
import {useUserStore} from "@/stores/userStore";
const userStore = useUserStore();
...
//form实例统一校验
const formRef = ref(null);
const router = useRouter();
const doLogin = () => {
formRef.value.validate(async (valid) => {
// valid: 所有表单都通过校验 才为true
//console.log(valid)
if (valid) {
//console.log(form.value)
const {account, password} = form.value
//const res = await loginAPI({account, password});
const res = await userStore.getUserInfo({account, password});
//console.log(res)
ElMessage({type: 'success', message: '登录成功'})
router.replace({path: '/'})
}
})
}
步骤2:重构导航栏用户登录状态模板
重构LayoutNav.vue
<script setup>
import {useUserStore} from "@/stores/userStore";
const userStore = useUserStore();
</script>
<template>
<nav class="app-topnav">
<div class="container">
<ul>
<template v-if="userStore.userInfo.token">
<li><a href="javascript:;"><i class="iconfont icon-user"></i>{{ userStore.userInfo.account }}</a></li>
步骤3:用户数据持久化
1-安装pinia数据持久化插件
npm i pinia-plugin-persistedstate
2-重构main.js
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const app = createApp(App)
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate)
app.use(pinia)
3-重构userStore.js
export const useUserStore = defineStore('user', () => {
// 1. 定义管理用户数据的state
const userInfo = ref({})
// 2. 定义获取接口数据的action函数
const getUserInfo = async (user) => {
const res = await loginAPI(user)
userInfo.value = res.result
}
// 3. 以对象的格式把state和action return
return {
userInfo,
getUserInfo,
}
},{
persist:true
})
4-重启服务器,测试数据持久性
退出登录实现
基础思想:
- 清除用户信息
- 跳转到登录页
1- 新增清除用户信息action
// 退出时清除用户信息
const clearUserInfo = () => {
userInfo.value = {}
}
2- 组件中执行业务逻辑
<script setup>
import { useUserStore } from '@/stores/userStore'
import { useRouter } from 'vue-router'
const userStore = useUserStore()
const router = useRouter()
const confirm = () => {
console.log('用户要退出登录了')
// 退出登录业务逻辑实现
// 1.清除用户信息 触发action
userStore.clearUserInfo()
// 2.跳转到登录页
router.push('/login')
}
</script>
<el-popconfirm @confirm="confirm" title="确认退出吗?" confirm-button-text="确认" cancel-button-text="取消">
<template #reference>
<a href="javascript:;">退出登录</a>
</template>
</el-popconfirm>
token相关设置
##请求拦截器携带token
基础思想:很多接口如果想要获取数据必须要带着有效的Token信息才可以,拦截器中做一次,用到axios实例的其他都可以拿到
// axios请求拦截器
http.interceptors.request.use(config => {
const userStore = useUserStore();
const token = userStore.userInfo.token;
if(token){
config.headers.Authorization = `Bearer ${token}`
}
return config
}, e => Promise.reject(e))
请求测试效果
响应拦截器处理token失效
// axios响应式拦截器
http.interceptors.response.use(res => res.data, e => {
//统一错误提示
ElMessage({
type: 'error',
message: e.response.data.message
})
//401token失效处理
const userStore = useUserStore();
if(e.response.status === 401){
userStore.clearUserInfo()
router.push('/login')
}
return Promise.reject(e)
})