在 Vue 项目中,我们经常使用状态管理(如 Vuex 或 Pinia)来管理用户登录状态、主题、页面设置等全局数据。但很多朋友会遇到一个问题:
“我刷新页面之后,状态就丢了啊!”
这时候,localStorage 就是你的好搭档!它能让你在用户刷新页面或关闭浏览器后,还能保留关键数据。
今天我们就来聊聊:如何优雅地将 localStorage 与 Vue 状态管理结合起来,实现数据持久化?
场景 | 问题 | 解决方案 |
---|---|---|
用户登录后刷新页面 | 状态丢失 | 用 localStorage 持久化 token |
用户设置了主题 | 刷新后恢复默认 | 从 localStorage 恢复主题配置 |
用户勾选了“记住我” | 页面关闭后还要保留 | 使用 localStorage 保留选项 |
虽然 Vuex / Pinia 很强大,但它们本身不持久化数据,页面刷新后会重新初始化。而 localStorage 恰好可以把状态“存活”下来,二者搭配使用堪称完美组合。
我们以 Pinia
为例(Vue 3 推荐使用),演示一个简单的“用户登录信息持久化”功能。
npm install pinia
在项目入口处(main.ts / main.js)注册:
import { createPinia } from 'pinia'
app.use(createPinia())
// stores/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
token: localStorage.getItem('token') || '',
username: localStorage.getItem('username') || '',
}),
actions: {
login(payload: { token: string, username: string }) {
this.token = payload.token
this.username = payload.username
// 存入 localStorage
localStorage.setItem('token', payload.token)
localStorage.setItem('username', payload.username)
},
logout() {
this.token = ''
this.username = ''
localStorage.removeItem('token')
localStorage.removeItem('username')
},
},
})
✅ 说明:
localStorage
读取,保证页面刷新后不丢失;localStorage
,确保数据一致;
当前用户:{{ userStore.username }}
页面刷新后,userStore.username
和 token
都能恢复,不再丢失!
如果你项目中很多地方要读写 localStorage,建议使用 VueUse 提供的 useStorage
:
import { useStorage } from '@vueuse/core'
const token = useStorage('token', '')
它会自动保持响应式,并同步 localStorage,无需手动 setItem/getItem,非常方便。
技巧 | 用途 |
---|---|
封装 setLocalStorage 与 getLocalStorage 方法 |
增强可维护性 |
使用 JSON.stringify/parse 存对象 |
保持格式一致 |
可用 sessionStorage 替代 localStorage |
页面关闭即清除更安全 |
加入过期机制(如存时间戳) | 控制存储有效期 |
使用插件自动持久化(如 pinia-plugin-persistedstate ) |
让状态自动同步本地 |
存在哪 | 适合存什么 |
---|---|
Vuex / Pinia | 纯前端临时状态 |
localStorage | 持久化配置、用户信息 |
二者结合 | 保持数据持久、组件响应式不变 |
页面刷新不丢状态 是用户体验的加分项。结合 localStorage
,你可以轻松实现“半持久化”的全局状态管理,又不会丢掉 Vue 的响应式优势。
如果你看到这里说明你真的对这个主题感兴趣啦!别忘了给我 点赞 + 收藏 + 关注 支持一下 !
你还想了解哪些 Vue 实战技巧?比如:
sessionStorage
和 localStorage
的切换策略?Pinia
自动持久化插件的使用?欢迎评论区告诉我,下次写你想看的!