拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Vue Vben Admin 状态管理指南:@vben/stores 的 User Store 与 Timezone Store 实战解析

Vue Vben Admin 状态管理指南vben/stores 的 User Store 与 Timezone Store 实战解析【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin导读在 Vue Vben Admin基于 Vue 3 Pinia 的现代中后台管理模板中vben/stores是统一封装的状态管理包内置了用户信息、权限、页签、时区等核心 Store。本篇以官方文档 docs/src/guide/essentials/stores.md 为主线深入讲解useUserStore与useTimezoneStore的 API 用法、持久化策略与底层实现并结合 packages/stores/src 源码与测试用例帮助你在业务侧正确、规范地使用这些 Store实现用户信息同步、角色管理与时区偏好持久化。一、包结构速览vben/stores提供了什么vben/stores是独立发包的状态管理模块其入口文件 packages/stores/src/index.ts 内容如下export * from ./modules; export * from ./setup; export { defineStore, storeToRefs } from pinia;也就是说该包除导出各业务 Store 与初始化函数外同时重新导出了 pinia 的defineStore与storeToRefs业务侧可以统一从vben/stores引入无需再单独安装或从pinia直接导入。所有 Store 定义集中在 packages/stores/src/modules 目录下文件Storestore id职责user.tsuseUserStorecore-user用户信息与角色access.tsuseAccessStorecore-access权限码、菜单、路由、Token、锁屏等tabbar.tsuseTabbarStorecore-tabbar多页签状态timezone.tsuseTimezoneStorecore-timezone时区状态setup store各 Store 均通过acceptHMRUpdate处理开发期热更新见 user.ts、timezone.ts保证模块热替换时状态不丢失。vben/stores已在各个app如apps/web-antd、playground等下统一引入业务代码无需单独安装直接 import 即可。二、全局初始化initStores与持久化插件在深入单个 Store 前先了解它的运行底座。setup.ts 中的initStores(app, options)完成三件事创建createPinia()实例安装pinia-plugin-persistedstate持久化插件通过app.use(pinia)注册到应用。其中值得注意的持久化细节命名空间隔离initStores接收{ namespace }选项持久化 key 格式为${namespace}-${store.id}。由于vben/stores是共享包后续可能存在多个 app 共用的情况配置不同的命名空间可防止缓存冲突开发/生产差异化存储开发环境import.meta.env.DEV直接使用localStorage生产环境则通过secure-ls以AES 加密 压缩的方式写入加密密钥来自import.meta.env.VITE_APP_STORE_SECURE_KEYmeta 前缀为${namespace}-secure-meta见 setup.ts统一重置resetAllStores()遍历 pinia 实例内部的所有 store 并调用其$reset()用于退出登录等场景的全局状态清理。注意pinia-plugin-persistedstate是运行时动态 import的这意味着vben/stores本身不把持久化插件作为强依赖打进包内。三、用户信息 StoreuseUserStore3.1 状态定义useUserStore的 store id 为core-user采用options store风格定义。状态结构定义在 user.ts字段默认值说明userInfonull用户信息类型BasicUserInfo \| null来自vben-core/typingsuserRoles[]用户角色列表string[]3.2 设置用户信息setUserInfosetUserInfo(userInfo)在写入用户信息的同时自动从userInfo.roles同步角色到userRoles。源码见 user.tssetUserInfo(userInfo: BasicUserInfo | null) { this.userInfo userInfo; const roles userInfo?.roles ?? []; this.setUserRoles(roles); }注意userInfo?.roles ?? []当传入null或缺少roles字段时角色会被重置为空数组。这一行为有对应的单元测试验证user.test.ts将setUserInfo(null)后userInfo为null且userRoles清空为[]。典型用法import { useUserStore } from vben/stores; const userStore useUserStore(); userStore.setUserInfo({ id: 1, name: vben, roles: [admin] }); userStore.userRoles; // [admin]持久化策略useUserStore未配置persist源码中无 persist 配置项。原因在于用户信息属于运行时态——通常在登录后由接口返回退出登录后即失效不适合写入 localStorage 造成信息残留或过期。3.3 设置用户角色setUserRolessetUserRoles(roles)直接覆盖角色列表user.tssetUserRoles(roles: string[]) { this.userRoles roles; }import { useUserStore } from vben/stores; const userStore useUserStore(); userStore.setUserRoles([admin, editor]); userStore.userRoles; // [admin, editor]3.4 获取用户信息useUserStore未提供专门的 getter直接访问 state 即可读取需要响应式解构时使用storeToRefs推荐统一从vben/stores引入import { storeToRefs, useUserStore } from vben/stores; const userStore useUserStore(); // 直接访问 userStore.userInfo; userStore.userRoles; // 保持响应式模板/计算属性中推荐 const { userInfo, userRoles } storeToRefs(userStore);storeToRefs的解构结果会保持响应性适合在computed、watch或模板中使用而直接const { userInfo } userStore会丢失响应性需要避免。四、时区 StoreuseTimezoneStore4.1 Store 设计useTimezoneStore的 store id 为core-timezone采用setup store风格封装源码见 timezone.ts。暴露的成员如下名称说明timezone当前时区初始值取自getCurrentTimezone()refsetTimezone(timezone)设置时区并同步到 dayjs 默认时区getTimezoneOptions()获取时区选项列表默认来自DEFAULT_TIME_ZONE_OPTIONS$reset()重置时区到getCurrentTimezone()4.2 底层getCurrentTimezone/setCurrentTimezone时区的初始值与 dayjs 同步逻辑来自vben-core/shared的 date.tslet currentTimezone getSystemTimezone(); export const setCurrentTimezone (timezone?: string) { currentTimezone timezone || getSystemTimezone(); dayjs.tz.setDefault(currentTimezone); }; export const getCurrentTimezone () currentTimezone;要点模块内维护了一个currentTimezone变量未显式设置时默认取dayjs.tz.guess()推断的系统时区setCurrentTimezone(timezone)会同时调用dayjs.tz.setDefault()因此只有经过setTimezone或initTimezone的时区才会真正影响 dayjs 的全局默认时区对应的单元测试见 date.test.ts设置Asia/Shanghai后getCurrentTimezone()返回该值无参调用则回退到系统推断时区。4.3 设置时区setTimezonesetTimezone(timezone)依次执行调用当前时区处理器的setTimezone如有→ 更新内部timezoneRef→ 调用setCurrentTimezone同步 dayjs 默认时区。核心实现timezone.tsasync function setTimezone(timezone: string) { const timezoneHandler getTimezoneHandler(); await timezoneHandler.setTimezone?.(timezone); timezoneRef.value timezone; setCurrentTimezone(timezone); }用法import { useTimezoneStore } from vben/stores; const store useTimezoneStore(); await store.setTimezone(America/New_York); store.timezone; // America/New_York4.4 获取时区选项getTimezoneOptionsgetTimezoneOptions()返回{ label, value }[]形式的选项列表默认由DEFAULT_TIME_ZONE_OPTIONS映射而来若通过setTimezoneHandler注入了自定义getTimezoneOptions则以自定义实现为准。默认选项定义在 constants.ts包含纽约GMT-5、伦敦GMT0、上海GMT8、东京GMT9、首尔GMT9五个常见时区映射时把timezone字段转为value// 默认处理器getDefaultTimezoneHandler getTimezoneOptions: () { return Promise.resolve( DEFAULT_TIME_ZONE_OPTIONS.map((item) ({ label: item.label, value: item.timezone, })), ); },用法import { useTimezoneStore } from vben/stores; const store useTimezoneStore(); const options await store.getTimezoneOptions(); // [{ label: America/New_York(GMT-5), value: America/New_York }, ...]4.5 重置时区$reset()$reset()仅将内部timezoneRef重置为getCurrentTimezone()的返回值不会调用setCurrentTimezone因此不会同步 dayjs 默认时区——只有setTimezone才会同步timezone.tsfunction $reset() { timezoneRef.value getCurrentTimezone(); }import { useTimezoneStore } from vben/stores; const store useTimezoneStore(); store.$reset(); store.timezone; // 回到 getCurrentTimezone() 的值4.6 注入自定义时区处理器setTimezoneHandlersetTimezoneHandler(handler)用于注入自定义时区处理模块可覆盖getTimezone/getTimezoneOptions/setTimezone三个方法典型场景是对接后端接口存储用户时区偏好。其实现采用默认处理器 自定义处理器浅合并的策略timezone.tslet customTimezoneHandler: null | PartialTimezoneHandler null; const setTimezoneHandler (handler: PartialTimezoneHandler) { customTimezoneHandler handler; }; const getTimezoneHandler () ({ ...getDefaultTimezoneHandler(), ...customTimezoneHandler, });TimezoneHandler接口定义timezone.tsinterface TimezoneHandler { getTimezone?: () Promisenull | string | undefined; getTimezoneOptions?: () Promise{ label: string; value: string }[]; setTimezone?: (timezone: string) Promisevoid; }示例将时区读写接入后端接口import { setTimezoneHandler, useTimezoneStore } from vben/stores; setTimezoneHandler({ async getTimezone() { return (await fetchUserSettings()).timezone; }, async setTimezone(timezone) { await saveUserSettings({ timezone }); }, async getTimezoneOptions() { return [{ label: 东八区, value: Asia/Shanghai }]; }, }); const store useTimezoneStore(); await store.setTimezone(Asia/Shanghai);注意setTimezoneHandler注入的是运行时配置不会被持久化且它需在useTimezoneStore使用前调用才生效。仓库 playground 中给出了完整示例 playground/src/timezone-init.ts在应用启动时用getTimezoneApi/getTimezoneOptionsApi/setTimezoneApi三个接口封装注入。此外setup store 内部在初始化时创建 store 实例时会立即调用一次initTimezone()若自定义处理器提供了getTimezone则用其返回值覆盖初始时区并同步 dayjs 默认时区异常会被捕获并打印Failed to initialize timezone during store setup警告timezone.ts。4.7 持久化策略useTimezoneStore通过pinia-plugin-persistedstate持久化配置如下timezone.tspersist: { // 持久化 pick: [timezone], }含义仅timezone字段会被持久化刷新页面后时区偏好得以保留持久化的存储介质由全局initStores决定开发环境localStorage生产环境 AES 加密存储key 形如${namespace}-core-timezonesetTimezoneHandler注入的处理逻辑属于运行时配置不持久化——因此刷新页面后若后端有用户时区偏好仍会优先由getTimezone经initTimezone拉取覆盖。五、业务落地建议结合源码与文档在业务中使用vben/stores时有几点实践建议统一引入路径defineStore、storeToRefs及各 Store 一律从vben/stores导入保持依赖收敛用户信息赋值用setUserInfo它会自动同步roles到userRoles避免手动重复赋值登出时调用setUserInfo(null)即可一次性清空用户信息与角色有测试保障见 user.test.ts响应式读取用storeToRefs在组件/组合式函数中解构userInfo、userRoles、timezone时务必通过storeToRefs保持响应性时区接入后端在应用入口如 playground 的 timezone-init.ts调用setTimezoneHandler注入getTimezone/setTimezone/getTimezoneOptions即可将用户时区偏好落到服务端同时利用timezone字段的持久化保证刷新后不回退需要全局清理时使用initStores返回的 pinia 实例配合resetAllStores()统一重置setup.ts典型场景是切换账号后的状态复位。六、小结vben/stores通过 options storeuseUserStore与 setup storeuseTimezoneStore两种风格分别承载用户信息/角色与全局时区两类跨页面状态useUserStore无持久化用户信息随登录态生命周期存在setUserInfo自动同步角色useTimezoneStore持久化timezone字段通过setTimezoneHandler可无缝对接后端时区偏好接口并始终与 dayjs 默认时区保持同步。理解这两个 Store 的 API 与底层实现packages/stores/src/modules/user.ts、packages/stores/src/modules/timezone.ts、packages/core/base/shared/src/utils/date.ts即可在业务代码中规范、安全地管理这两类全局状态。【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门