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

在你的代码中,userInfo 的浏览器本地存储是在 defineStore("user", () => { ... }) 函数内部的第一行实现的

auth.ts

// 访问 token 缓存的 key const ACCESS_TOKEN_KEY = "access_token"; // 刷新 token 缓存的 key const REFRESH_TOKEN_KEY = "refresh_token";  function getAccessToken(): string {   return localStorage.getItem(ACCESS_TOKEN_KEY) || ""; }  function setAccessToken(token: string) {   localStorage.setItem(ACCESS_TOKEN_KEY, token); }  function getRefreshToken(): string {   return localStorage.getItem(REFRESH_TOKEN_KEY) || ""; }  function setRefreshToken(token: string) {   localStorage.setItem(REFRESH_TOKEN_KEY, token); }  function clearToken() {   localStorage.removeItem(ACCESS_TOKEN_KEY);   localStorage.removeItem(REFRESH_TOKEN_KEY); }  export { getAccessToken, setAccessToken, clearToken, getRefreshToken, setRefreshToken };  
 import { setAccessToken, setRefreshToken, getRefreshToken, clearToken } from "@/utils/auth";  export const useUserStore = defineStore("user", () => {   const userInfo = useStorage<UserInfo>("userInfo", {} as UserInfo);   const roleList = useStorage<RoleInfo[]>("roleList", []);         /**    * 登录    *    * @param {LoginFormData}    * @returns    */   function login(LoginFormData: LoginFormData) {     return new Promise<void>((resolve, reject) => {       console.log("modules.user.login");       AuthAPI.login(LoginFormData)         .then((data) => {           const { accessToken, user } = data;           setAccessToken(accessToken);           if (User.RoleList && Array.isArray(user.RoleList)) {             roleList.value = user.RoleList;           } else {             roleList.value = []; // 确保总是数组             console.warn("RoleList is not an array or is undefined");           }           resolve();         })         .catch((error) => {           reject(error);         });     });   }        /**    * 获取用户信息    *    * @returns {UserInfo} 用户信息    */   function getUserInfo() {     return new Promise<UserInfo>((resolve, reject) => {       UserAPI.getInfo()         .then((data) => {           if (!data) {             reject("Verification failed, please Login again.");             return;           }           Object.assign(userInfo.value, { ...data });           resolve(data);         })         .catch((error) => {           reject(error);         });     });   } 

这行代码是关键,

const userInfo = useStorage<UserInfo>("userInfo", {} as UserInfo); 

它使用了 useStorage 函数(通常来自 @vueuse/core 或类似的工具库)来创建一个响应式的引用,该引用会自动将数据持久化到浏览器的本地存储中。

具体分析:

  1. 存储时机:当调用 getUserInfo() 方法时,通过这行代码:

    Object.assign(userInfo.value, { ...data }); 

    将获取到的用户数据赋值给 userInfo.value,此时 useStorage 会自动将这些数据保存到 localStorage。

  2. 存储位置:数据会被存储在浏览器的 localStorage 中,键名为 "userInfo"

  3. 自动持久化useStorage 会自动处理:

    • 初始时从 localStorage 读取数据
    • 数据变更时自动写入 localStorage
    • 页面刷新后数据仍然保持

验证方式
你可以在浏览器开发者工具中查看:

  1. 打开「Application」标签页
  2. 选择「Local Storage」
  3. 查看你的网站域名下是否存在 userInfo 这个键,其值就是序列化的用户信息

注意clearUserData() 函数中没有直接清除 userInfo,你可能需要在其中添加:

userInfo.value = {} as UserInfo;     // 保持响应式一致性 roleList.value = [] as RoleInfo[];   // 保持响应式一致性 

来确保用户登出时本地存储的用户信息也被清除。

localStorage 与 useStorage 的区别

localStorage(原生 API)

直接操作本地存储的原生浏览器 API

// 存储数据 localStorage.setItem('userInfo', JSON.stringify(userData));  // 读取数据 const data = JSON.parse(localStorage.getItem('userInfo') || '{}');  // 删除数据 localStorage.removeItem('userInfo');  // 清空所有 localStorage.clear(); 

特点

  • ✅ 浏览器原生支持,无需额外依赖
  • ❌ 需要手动序列化/反序列化(JSON.stringify/JSON.parse)
  • ❌ 不是响应式的,数据变更不会自动更新界面
  • ❌ 需要手动处理存储和读取逻辑

useStorage(VueUse 工具函数)

基于 localStorage 封装的响应式工具函数

import { useStorage } from '@vueuse/core';  // 自动处理序列化和响应式 const userInfo = useStorage('userInfo', {} as UserInfo);  // 直接赋值,自动保存到 localStorage userInfo.value = newData;  // 读取数据,直接使用即可 console.log(userInfo.value); 

特点

  • ✅ 自动序列化/反序列化
  • ✅ 响应式,数据变更自动更新界面
  • ✅ 与 Vue 响应式系统无缝集成
  • ✅ 类型安全(TypeScript 支持)
  • ❌ 需要安装 @vueuse/core 依赖

对比示例

使用 localStorage

// 需要手动处理 const user = ref(JSON.parse(localStorage.getItem('userInfo') || '{}'));  function updateUser(newData) {   user.value = newData;   localStorage.setItem('userInfo', JSON.stringify(newData)); // 手动保存 } 

使用 useStorage

// 自动处理一切 const user = useStorage('userInfo', {});  function updateUser(newData) {   user.value = newData; // 自动保存到 localStorage } 

总结

特性 localStorage useStorage
响应式 ❌ 否 ✅ 是
自动序列化 ❌ 需要手动 ✅ 自动
Vue 集成 ❌ 需要封装 ✅ 无缝集成
类型安全 ❌ 有限 ✅ 完整TS支持
使用便捷性 ❌ 较低 ✅ 极高

推荐使用 useStorage,特别是在 Vue 项目中,它能极大简化本地存储的操作并提供更好的开发体验。

删除 userInfo 的 key 方法

1. 使用 useStorage 的推荐方式

如果你使用的是 @vueuse/coreuseStorage

import { useStorage } from '@vueuse/core';  // 清除数据并移除 key function clearUserData() {   return new Promise<void>((resolve) => {     clearToken();     usePermissionStoreHook().resetRouter();     useDictStoreHook().clearDictionaryCache();     //清除数据,key 还在     userInfo.value = {} as UserInfo;     // 推荐方式:直接设置为 null 或 undefined,useStorage 会自动移除 key     userInfo.value = null as any;     // 或者     // userInfo.value = undefined as any;          resolve();   }); } 

2. 手动删除 localStorage 的 key

function clearUserData() {   return new Promise<void>((resolve) => {     clearToken();     usePermissionStoreHook().resetRouter();     useDictStoreHook().clearDictionaryCache();          // 方式1:直接操作 localStorage     localStorage.removeItem('userInfo');          // 方式2:如果还想保持响应式,需要重新赋值     userInfo.value = {} as UserInfo;          resolve();   }); } 

3. 完整的清除方案

/**  * 清理用户数据(完全清除)  */ function clearUserDataCompletely() {   return new Promise<void>((resolve) => {     clearToken();     usePermissionStoreHook().resetRouter();     useDictStoreHook().clearDictionaryCache();          // 方案A:使用 localStorage.removeItem(推荐)     localStorage.removeItem('userInfo');     userInfo.value = {} as UserInfo; // 保持响应式一致性          // 方案B:设置为 null/undefined(useStorage 会自动处理)     // userInfo.value = null as any;          resolve();   }); } 

4. 验证 key 是否被删除

// 检查 key 是否存在的方法 function isUserInfoKeyExists(): boolean {   return localStorage.getItem('userInfo') !== null; }  // 使用示例 console.log('userInfo key exists:', isUserInfoKeyExists()); // false 

推荐方案

在你的 clearUserData 函数中这样实现

function clearUserData() {   return new Promise<void>((resolve) => {     clearToken();     usePermissionStoreHook().resetRouter();     useDictStoreHook().clearDictionaryCache();          // 同时操作 localStorage 和响应式变量     localStorage.removeItem('userInfo'); // 删除 key     userInfo.value = {} as UserInfo;     // 重置响应式变量          resolve();   }); } 

这样就能确保:

  1. ✅ localStorage 中的 userInfo key 被完全删除
  2. ✅ 响应式变量保持一致性
  3. ✅ 下次访问时不会读取到旧的缓存数据
发表评论

评论已关闭。

相关文章