Pinia管理用户数据
基本思想:Pinia负责用户数据相关的state和action,组件中只负责触发action函数并传递参数
步骤1:创建userStore
1-创建store/userStore.js
import { loginAPI } from '@/apis/user'
export const useUserStore = defineStore('user', () => {// 1. 定义管理用户数据的stateconst userInfo = ref({})// 2. 定义获取接口数据的action函数const getUserInfo = async (user) => {const res = await loginAPI(user)userInfo.value = res.result}// 3. 以对象的格式把state和action returnreturn {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. 定义管理用户数据的stateconst userInfo = ref({})// 2. 定义获取接口数据的action函数const getUserInfo = async (user) => {const res = await loginAPI(user)userInfo.value = res.result}// 3. 以对象的格式把state和action returnreturn {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.清除用户信息 触发actionuserStore.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)
})