Vue element admin 浏览器本地存储 localStorage、useStorage

Vue Element Admin 浏览器本地存储:从 localStorage 到 useStorage 的优雅之路

一、为什么需要本地存储?在开发后台管理系统时,我们经常会遇到这样的场景:用户登录后,页面刷新一下,用户信息就丢了,又得重新登录。或者用户设置了一些偏好(比如表格的列宽、主题颜色),刷新一下就回到默认状态了。这是因为 Vue 是单页应用(SPA),数据默认存储在内存中,刷新页面后内存被清空。为了解决这个问题,我们需要把数据持久化到浏览器的本地存储中。## 二、传统 localStorage 的使用### 2.1 什么是 localStorage?localStorage 是浏览器提供的一种本地存储机制,可以存储字符串类型的数据,容量一般在 5MB 左右,数据不会因为页面刷新而丢失,除非用户手动清除或者通过代码删除。### 2.2 基本使用方式javascript// 存储数据localStorage.setItem('userInfo', JSON.stringify({ name: '张三', age: 25, role: 'admin'}));// 读取数据const userInfo = JSON.parse(localStorage.getItem('userInfo'));console.log(userInfo); // {name: '张三', age: 25, role: 'admin'}// 删除数据localStorage.removeItem('userInfo');// 清空所有数据localStorage.clear();### 2.3 在 Vue Element Admin 中的传统实现在 Vue Element Admin 框架中,我们通常会在 src/utils/auth.js 中封装 localStorage 的操作:javascript// src/utils/auth.jsconst TokenKey = 'Admin-Token'export function getToken() { return localStorage.getItem(TokenKey)}export function setToken(token) { return localStorage.setItem(TokenKey, token)}export function removeToken() { return localStorage.removeItem(TokenKey)}然后在 Vuex 中使用这些方法:javascript// store/modules/user.jsimport { getToken, setToken, removeToken } from '@/utils/auth'const state = { token: getToken(), // 从 localStorage 初始化 userInfo: null}const mutations = { SET_TOKEN: (state, token) => { state.token = token setToken(token) // 同步到 localStorage }, REMOVE_TOKEN: (state) => { state.token = '' removeToken() // 从 localStorage 删除 }}### 2.4 传统方式的痛点1. 手动序列化/反序列化 :每次都要写 JSON.stringifyJSON.parse2. 数据不同步 :修改了 localStorage 不会自动更新组件3. 类型丢失 :存储的数字、布尔值都会变成字符串4. 代码冗余 :每个数据项都要写 get、set、remove 三个方法## 三、useStorage:Vue 3 组合式 API 的优雅方案### 3.1 什么是 useStorage?useStorage 是 VueUse 库提供的一个组合式 API,它把 localStorage 的操作封装成了响应式的 ref 对象,实现了数据的双向绑定。### 3.2 安装 VueUsebashnpm install @vueuse/core### 3.3 基本使用javascriptimport { useStorage } from '@vueuse/core'// 存储字符串const token = useStorage('admin-token', 'default-token')// 存储对象const userInfo = useStorage('user-info', { name: '', age: 0})// 存储数组const permissions = useStorage('user-permissions', [])### 3.4 在 Vue Element Admin 中的应用让我们看看如何在 Vue Element Admin 中优雅地使用 useStoragejavascript// store/modules/user.jsimport { defineStore } from 'pinia'import { useStorage } from '@vueuse/core'export const useUserStore = defineStore('user', { state: () => ({ // 使用 useStorage 实现响应式本地存储 token: useStorage('admin-token', ''), userInfo: useStorage('user-info', { id: null, name: '', avatar: '', roles: [] }), // 登录时间戳,用于判断 token 是否过期 loginTime: useStorage('login-time', 0) }), getters: { // 判断是否登录 isLoggedIn: (state) => !!state.token, // 获取用户角色 userRoles: (state) => state.userInfo.roles, // 判断 token 是否过期(假设 7 天过期) isTokenExpired: (state) => { const now = Date.now() const sevenDays = 7 * 24 * 60 * 60 * 1000 return (now - state.loginTime) > sevenDays } }, actions: { // 登录成功后保存用户信息 loginSuccess(data) { this.token = data.token this.userInfo = { id: data.id, name: data.name, avatar: data.avatar, roles: data.roles } this.loginTime = Date.now() }, // 登出 logout() { this.token = '' this.userInfo = { id: null, name: '', avatar: '', roles: [] } this.loginTime = 0 // 注意:useStorage 会自动同步到 localStorage,无需手动调用 } }})### 3.5 完整的实战示例下面是一个完整的用户设置页面的例子,展示了 useStorage 的强大之处:vue<template> <div class="user-settings"> <el-card> <template #header> <span>用户设置</span> </template> <el-form :model="settings" label-width="100px"> <!-- 主题设置 --> <el-form-item label="主题颜色"> <el-color-picker v-model="settings.themeColor" /> <span class="hint">当前颜色:{````{ settings.themeColor }}</span> </el-form-item> <!-- 语言设置 --> <el-form-item label="显示语言"> <el-select v-model="settings.language"> <el-option label="中文" value="zh" /> <el-option label="English" value="en" /> </el-select> </el-form-item> <!-- 表格设置 --> <el-form-item label="每页条数"> <el-input-number v-model="settings.pageSize" :min="10" :max="100" :step="10" /> </el-form-item> <!-- 通知设置 --> <el-form-item label="消息通知"> <el-switch v-model="settings.notificationEnabled" /> </el-form-item> <!-- 操作按钮 --> <el-form-item> <el-button type="primary" @click="saveSettings">保存设置</el-button> <el-button @click="resetSettings">重置默认</el-button> <el-button @click="showSettings">查看当前设置</el-button> </el-form-item> </el-form> </el-card> </div></template><script setup>import { useStorage } from '@vueuse/core'import { ElMessage } from 'element-plus'// 使用 useStorage 创建响应式设置对象// 所有修改都会自动同步到 localStorageconst settings = useStorage('user-settings', { themeColor: '#409EFF', // 默认主题色 language: 'zh', // 默认语言 pageSize: 20, // 默认每页条数 notificationEnabled: true, // 默认开启通知 sidebarCollapsed: false, // 侧边栏状态 lastLoginTime: null // 上次登录时间})// 保存设置function saveSettings() { // useStorage 自动同步,无需手动操作 localStorage ElMessage.success('设置已保存(自动同步到 localStorage)') // 打印当前 localStorage 中的值 console.log('localStorage 中的值:', JSON.parse(localStorage.getItem('user-settings')) )}// 重置为默认值function resetSettings() { settings.value = { themeColor: '#409EFF', language: 'zh', pageSize: 20, notificationEnabled: true, sidebarCollapsed: false, lastLoginTime: null } ElMessage.success('已重置为默认设置')}// 查看当前设置function showSettings() { ElMessage.info(`当前设置:主题色 ${settings.themeColor},语言 ${settings.language},每页 ${settings.pageSize} 条`)}// 监听设置变化watch(settings, (newVal) => { console.log('设置已更新,同步到 localStorage')}, { deep: true })</script><style scoped>.hint { margin-left: 10px; font-size: 12px; color: #909399;}</style>## 四、useStorage 的高级特性### 4.1 自定义序列化有些时候,我们需要存储 Date 对象或其他特殊类型,可以通过自定义序列化器来实现:javascriptimport { useStorage } from '@vueuse/core'// 自定义序列化器const customSerializer = { read: (v) => JSON.parse(v, (key, value) => { // 自动转换日期字符串为 Date 对象 if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value)) { return new Date(value) } return value }), write: (v) => JSON.stringify(v)}// 使用自定义序列化器const dateSettings = useStorage('date-settings', { lastVisit: new Date(), reminders: []}, localStorage, { serializer: customSerializer })### 4.2 监听 localStorage 变化当其他标签页修改了 localStorage 时,useStorage 可以自动感知:javascriptimport { useStorage, useEventListener } from '@vueuse/core'const token = useStorage('admin-token', '')// 监听 storage 事件(其他标签页修改时触发)useEventListener(window, 'storage', (event) => { if (event.key === 'admin-token') { console.log('其他标签页修改了 token') // token 的值会自动更新 }})## 五、性能优化建议1. 合理设置默认值 :避免频繁修改导致大量写入2. 使用 debounce :对于频繁变化的值(如搜索历史),可以使用防抖3. 定期清理 :对于过期的数据,定期清理javascriptimport { useStorage, useDebounceFn } from '@vueuse/core'// 搜索历史const searchHistory = useStorage('search-history', [])// 使用防抖,避免频繁写入const addSearch = useDebounceFn((keyword) => { if (keyword && !searchHistory.value.includes(keyword)) { searchHistory.value.unshift(keyword) // 只保留最近 20 条 if (searchHistory.value.length > 20) { searchHistory.value = searchHistory.value.slice(0, 20) } }}, 500)## 总结从传统的 localStorage 操作到 VueUse 的 useStorage,我们经历了从繁琐到优雅的转变。useStorage 不仅解决了手动序列化、数据同步等问题,还提供了响应式、类型安全、自定义序列化等高级特性。在 Vue Element Admin 项目中,合理使用 useStorage 可以:1. 减少样板代码 :不再需要手动 get/set/remove2. 保持数据同步 :响应式绑定,修改即存储3. 类型安全 :自动处理 JSON 序列化4. 跨标签页同步:自动监听 storage 事件建议在项目中使用 useStorage 替代传统的 localStorage 操作,让数据持久化变得简单而优雅。记住,好的工具不仅解决问题,更能提升开发体验。

相关推荐
手揽回忆怎么睡1 小时前
Ubuntu 22.04 64位安装MinIO
linux·前端·ubuntu
铁皮饭盒1 小时前
网页端OCR, 加载6mb大小模型, 又快又准, 百度这次真香
前端·后端
Web极客码2 小时前
如何在WordPress中添加动态内容
服务器·前端·wordpress
云浪2 小时前
给 AI Agent 加上语音交互:ASR + 流式 TTS 实战
前端·人工智能·后端
晓得迷路了2 小时前
栗子前端技术周刊第 140 期 - pnpm、Node 新 API 文档网站、Oxlint...
前端·javascript·node.js
烬羽2 小时前
一个队列,怎么让滑动窗口从 O(nk) 变 O(n)?单调队列彻底搞懂
javascript·数据结构·算法
weixin_3823952311 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__11 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.12 小时前
Vue3 Props 属性
前端·javascript·vue.js