不使用vuex-persist,如何在Vuex中保留用户状态至登出?
解决Vuex刷新后用户数据丢失但Token保留的问题(不存本地存储)
我完全理解你的困扰——明明Token和用户数据是一起拿到的,刷新后Token还在,用户信息却没了,还不能把敏感的用户数据存到localStorage或Cookie里。咱们先拆解一下问题根源,再一步步解决它。
问题根源
你看你的store.js里,token是从localStorage.getItem('token')初始化的,所以页面刷新后Vuex重置时,token能从本地读回来;但user初始是个空对象,刷新后没有任何逻辑去重新获取用户数据,自然就丢失了。
解决方案思路
既然不能把用户数据存在本地,那我们可以利用已保留的Token,在页面刷新后自动发起请求,从服务器重新获取用户信息,再把它放回Vuex里。这样既不用存敏感数据,又能恢复用户状态,直到用户主动登出。
具体步骤&代码修改
1. 在Store中完善逻辑,新增获取用户信息的Action
首先给你的store.js补充登录时的Token存储逻辑,再加一个用于拉取用户信息的Action:
// store.js state: { status: '', token: localStorage.getItem('token'), user: {} }, mutations: { auth_success(state, { token, user }) { state.status = 'success'; state.token = token; state.user = user; }, set_user(state, user) { // 新增单独设置用户的mutation,也可以复用auth_success state.user = user; }, auth_error(state) { state.status = 'error'; state.token = null; state.user = {}; } }, actions: { login({ commit }, user) { return new Promise((resolve, reject) => { commit('auth_request'); axios({ url: 'http://localhost:8085/login', data: user, method: 'POST' }) .then((resp) => { const token = resp.data.token; const user = resp.data.user; axios.defaults.headers.common['Authorization'] = token; localStorage.setItem('token', token); // 登录时要把token存到localStorage,不然刷新后拿不到 commit('auth_success', { token, user }); resolve(resp); }) .catch((err) => { commit('auth_error'); localStorage.removeItem('token'); reject(err); }); }) }, // 新增:用现有Token拉取用户信息 fetchUser({ commit, state }) { return new Promise((resolve, reject) => { if (!state.token) { reject('No token available'); return; } axios({ url: 'http://localhost:8085/user/info', method: 'GET' }) // 请替换成你后端的用户信息接口 .then((resp) => { commit('set_user', resp.data.user); resolve(resp); }) .catch((err) => { // 请求失败说明Token过期/无效,清空状态 commit('auth_error'); localStorage.removeItem('token'); reject(err); }); }) }, // 补充登出Action(如果还没加) logout({ commit }) { return new Promise((resolve) => { commit('auth_error'); localStorage.removeItem('token'); delete axios.defaults.headers.common['Authorization']; resolve(); }) } }, getters: { isLoggedIn(state) { return !!state.token; // 改成布尔值更符合逻辑 }, getUser(state){ return state.user; } }
注意:你需要后端提供一个通过Token验证获取用户信息的接口,请求时会自动带上Authorization头里的Token,后端验证通过后返回用户数据。
2. 在应用初始化时自动恢复用户状态
你可以在App.vue的mounted钩子中,或者路由全局守卫里,检查是否有Token但用户数据为空,如果是就调用fetchUser:
// App.vue <script> export default { mounted() { const hasToken = this.$store.getters.isLoggedIn; const hasUser = Object.keys(this.$store.getters.getUser).length > 0; if (hasToken && !hasUser) { this.$store.dispatch('fetchUser') .catch(err => { // 处理错误,比如跳转到登录页 this.$router.push('/login'); }); } } } </script>
更推荐用路由守卫(能覆盖所有页面跳转场景):
// router/index.js router.beforeEach((to, from, next) => { const isLoggedIn = store.getters.isLoggedIn; const hasUser = Object.keys(store.getters.getUser).length > 0; if (to.matched.some(record => record.meta.requiresAuth)) { if (!isLoggedIn) { next('/login'); } else if (isLoggedIn && !hasUser) { // 有Token但无用户数据,先拉取用户信息 store.dispatch('fetchUser') .then(() => next()) .catch(() => next('/login')); } else { next(); } } else { next(); } });
3. 优化组件的用户信息获取方式
你的User.vue里用mounted赋值的方式不是响应式的,改成计算属性会更可靠:
<template> <v-container> <v-layout row wrap> Welcome {{ user.fullName }} </v-layout> </v-container> </template> <script> export default { computed: { user() { return this.$store.getters.getUser; } } } </script>
这样当Vuex里的user更新时,组件会自动响应,不用手动调用方法。
方案优势
- 敏感的用户数据始终只存在Vuex和内存中,不会落地到本地存储,符合你的安全要求;
- 刷新页面后,利用已有的Token(仅Token存在localStorage,只要后端验证逻辑安全,风险可控)重新拉取用户数据,恢复状态;
- 用户主动登出时,清空Token和Vuex里的用户数据,状态自然消失。
内容的提问来源于stack exchange,提问作者Alexander F
相关产品推荐
相关产品推荐

