在你的代码中,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. 下次访问时不会读取到旧的缓存数据

Vue element admin 浏览器本地存储 localStorage、useStorage的更多相关文章

  1. Vue学习之---浏览器本地存储(8/17)

    博客园(纯干货):https://www.cnblogs.com/zheng-yuzhu/ 文章目录 1.基础知识 2.代码实例(localStorage.html) 3.测试效果 4.代码实例(se ...

  2. 移动端浏览器隐私模式/无痕模式使用本地存储localStorage/sessionStorage的问题

    移动端浏览器隐私模式/无痕模式使用本地存储localStorage/sessionStorage的问题 开发H5 webapp时经常需要使用本地存储,如localStorage和sessionStor ...

  3. jquery访问浏览器本地存储cookie,localStorage和sessionStorage

    前言:cookie,localStorage和sessionStorage都是浏览器本地存储数据的地方,其用法不尽相同:总结一下基本的用法. 一.cookie 定义: 存储在本地,容量最大4k,在同源 ...

  4. 浏览器本地存储(browser-storage,HTML5-localStorage > IE-UserData > Cookie)

    https://www.baidufe.com/component/browser-storage/index.html BrowserStorage是浏览器本地存储的一个解决方案,存储优先级依次为: ...

  5. html5的本地存储localStorage和sessionStorage

    html5的本地存储localStorage和sessionStorage html5中新增的比较重要的一个功能就是web storage来实现客户端本地存储数据,之前存储数据都是用cookie来实现 ...

  6. 本地存储localStorage sessionStorage 以及 session 和cookie的对比和使用

    cookie和session都是用来跟踪浏览器用户身份的会话方式. 1.验证当前服务中继续请求数据时,哪些缓存数据会随着发往服务器? 只有cookie中设置的缓存数据会发送到服务器端 2. 强调几点: ...

  7. 本地存储localStorage以及它的封装接口store.js的使用

    本地存储localStorage以及它的封装接口store.js的使用 sublime-text chrome javascript readyGo 2016年11月20日发布   0 推荐 9 收藏 ...

  8. 本地存储 localStorage

    本地存储localStorage 概念:window对象下面的属性,html5新增的,将5M大小的数据存储本地的浏览器上面. 浏览器支持存储5M大小 本地存储localStorage特点 本地存储属于 ...

  9. 用于浏览器本地存储的js插件 - jStorage

    简介 jStorage是一个跨浏览器的将key-value类型的数据存储到浏览器本地存储的js插件——jStorage支持所有主流浏览器,PC机(甚至包括是IE6)和移动终端均可用.此外,jStora ...

  10. HTML5 学习笔记(三)——本地存储(LocalStorage、SessionStorage、Web SQL Database)

    一.HTML4客户端存储 B/S架构的应用大量的信息存储在服务器端,客户端通过请求响应的方式从服务器获得数据,这样集中存储也会给服务器带来相应的压力,有些数据可以直接存储在客户端,传统的Web技术中会 ...

随机推荐

  1. update注入之我理解

    1.基本语法 update test.test_table set username='admin123',password=000 where id=1; update test.test_tabl ...

  2. Springboot笔记<6>Rest的使用和请求参数注解@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody

    Rest的使用和原理 Rest风格支持(使用HTTP请求方式动词来表示对资源的操作) • 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveU ...

  3. kubernetes主流网络方案Flannel分析

    一.Flannel简单说明 Flannel是kubernetes集群的CNI网络插件之一,实质上是一种overlay网络,flannel支持多种网络转发策略,常用的vxlan.hostgw等. 二.F ...

  4. [书籍精读]《CSS世界》精读笔记分享

    写在前面 书籍介绍:本书从前端开发人员的需求出发,以"流"为线索,从结构.内容到美化装饰等方面,全面且深入地讲解前端开发人员必须了解和掌握的大量的CSS知识点.同时,作者结合多年的 ...

  5. 开源项目丨 Taier 1.1 版本正式发布,新增功能一览为快

    2022 年 5 月 8 日,Taier 1.1 版本正式发布! 本次版本更新对 Flink 的支持升级到 Flink1.12,支持多种流类型任务,新版本的使用文档已在社区中推送,大家可以随时下载查阅 ...

  6. Python学习:PocketFlow中的RAG例子

    运行效果 例子地址:https://github.com/The-Pocket/PocketFlow/tree/main/cookbook/pocketflow-rag 什么是RAG(用PocketF ...

  7. H20 大模型推理系统环境配置踩坑

    基础环境 CPU:INTEL(R) XEON(R) PLATINUM 8558P 48 Cores 96 Threads × 2 GPU:NVIDIA H20-3e NVL 141G × 8,NVLI ...

  8. 运行yolo时候,查mmcv各个版本

    https://download.openmmlab.com/mmcv/dist/cu111/torch1.8.0/index.html

  9. .Net Core Winform 缩放比例不是100%设置界面只能看到一半问题

    <PropertyGroup> <TargetFramework>net8.0-windows</TargetFramework> <Nullable> ...

  10. dotnet (.Net) Core在不是Web 项目中使用HttpClientFactory正确用法

    在不是web 项目中也不是Api 中使用 HttpClientFactory 先需要添加 Microsoft.Extensions.DependencyInjection.Abstractions M ...