02.Vben Admin 源码学习:状态管理-项目配置

1,688

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

0x00 前言

本文将对 Vue-Vben-Admin 的状态管理实现源码进行分析解读,耐心读完,相信您一定会有所收获!

0x01 数据仓库

项目状态管理代码实现在 src/store/ 目录下, 使用新一代的状态管理器 Pinia , 具体特性详见 官网

文件 src/store/index.ts 中调用 createPinia() 创建一个pinia 实例,声明方法 setupStore() 并导出,在主入口文件中调用此方法即可将 pinia 实例注册到应用程序中。

同时单独将 pinia 实例导出,用于在 setup() 函数外使用 pinia store 实例。

import { createPinia } from 'pinia'; 
// 创建一个 pinia(根存储)
const store = createPinia();
// 注册到应用程序
export function setupStore(app: App<Element>) { 
  app.use(store);
}

// 单独将pinia 实例导出
export { store };

src/store/modules 目录下,各个文件中定义不同的 store 实例,主要用于项目配置、错误日志、国际化、锁屏、多标签、菜单路由权限、用户状态等状态管理。

├── store # 数据仓库
│   ├── index.ts
│   ├── modules  
│   │   ├── app.ts #  项目配置
│   │   ├── errorLog.ts # 错误日志
│   │   ├── locale.ts # 国际化/多语言
│   │   ├── lock.ts # 系统锁屏
│   │   ├── multipleTab.ts # 多标签
│   │   ├── permission.ts # 权限/菜单/路由
│   │   └── user.ts # 用户状态

接下来将对每个文件一一讲解。

0x02 app.ts 项目配置

文件 src\store\modules\app.ts 声明导出一个store实例 useAppStore 、一个方法 useAppStoreWithOut()用于没有使用 setup 组件时使用。

// 项目配置存储实例
export const useAppStore = defineStore({
  id: 'app',  // 也称为 name,是必要的,Pinia 使用它来将 store 连接到 devtools。
  state: {},
  getters: {}
  actions:{}   
});

export function useAppStoreWithOut() {
  return useAppStore(store);
} 

state

状态对象定义了主题模式、页面加载状态、项目配置、菜单状态快照等。

state: (): AppState => ({
  darkMode: undefined, // 主题模式  dark|light
  pageLoading: false, //  页面加载状态
  projectConfig: Persistent.getLocal(PROJ_CFG_KEY), // 项目配置 ProjectConfig
  beforeMiniInfo: {}, // BeforeMiniState 
}),

projectConfig 属性用于配置项目内展示的内容、布局、文本等效果,具体配置文件路径 src/settings/projectSetting.ts, 属性定义由于篇幅原因请直接查看官网的 项目配置说明

projectConfig的初始化值从缓存中获取,而不是从文件中引入,这个后面会有单独篇幅进行讲解。

beforeMiniInfo 属性用于当窗口缩小时记住菜单状态,并在恢复窗口时恢复这些状态(是否折叠、是否分割、类型、模式)。

export interface BeforeMiniState {
  menuCollapsed?: boolean; // 菜单折叠
  menuSplit?: boolean; // 分割菜单
  menuMode?: MenuModeEnum; // 菜单类型
  menuType?: MenuTypeEnum; // 菜单模式
} 

Getter

Getter 等同于 Store 状态的计算值(计算属性)。

getters: {
  // 页面加载状态
  getPageLoading(): boolean {
    return this.pageLoading;
  },
  // 主题模式
  getDarkMode(): 'light' | 'dark' | string {
    return this.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode;
  },
  // 菜单状态快照
  getBeforeMiniInfo(): BeforeMiniState {
    return this.beforeMiniInfo;
  },
  // 项目配置
  getProjectConfig(): ProjectConfig {
    return this.projectConfig || ({} as ProjectConfig);
  },
  // 头部配置 
  getHeaderSetting(): HeaderSetting {
    return this.getProjectConfig.headerSetting;
  },
  // 菜单配置 
  getMenuSetting(): MenuSetting {
    return this.getProjectConfig.menuSetting;
  },
  // 动画配置 
  getTransitionSetting(): TransitionSetting {
    return this.getProjectConfig.transitionSetting;
  },
  // 多标签配置
  getMultiTabsSetting(): MultiTabsSetting {}
    return this.getProjectConfig.multiTabsSetting;
  },
}, 

其中 getDarkMode() 根据 state.darkMode、localStorage 存储和 配置文件的定义值darkMode 进行计算。

// src\settings\designSetting.ts
export const darkMode = ThemeEnum.LIGHT;

Actions

Actions 相当于组件中的 methods,主要用于设置state对象。


actions: {
  // 设置页面加载状态
  setPageLoading(loading: boolean): void {
    this.pageLoading = loading;
  },
  // 设置主题模式 存于`localStorage`中
  setDarkMode(mode: ThemeEnum): void {
    this.darkMode = mode;
    localStorage.setItem(APP_DARK_MODE_KEY_, mode);
  },
  // 设置页面加载状态
  setBeforeMiniInfo(state: BeforeMiniState): void {
    this.beforeMiniInfo = state;
  },
  // 设置项目配置 项目自带的缓存类进行缓存操作
  setProjectConfig(config: DeepPartial<ProjectConfig>): void {
    this.projectConfig = deepMerge(this.projectConfig || {}, config);
    Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig);
  },
  // 重置路由
  async resetAllState() {
    resetRouter();
    Persistent.clearAll(); // 清空缓存
  },
  // 使用定时器设置页面加载状态 
  async setPageLoadingAction(loading: boolean): Promise<void> {
    if (loading) {
      clearTimeout(timeId);
      // Prevent flicker  防止闪烁
      timeId = setTimeout(() => {
        this.setPageLoading(loading);
      }, 50);
    } else {
      this.setPageLoading(loading);
      clearTimeout(timeId);
    }
  },
},

其他

在缓存、localStorage操作中使用了存储KEY,它定义在 src\enums\cacheEnum.ts 文件中。


import { APP_DARK_MODE_KEY_, PROJ_CFG_KEY } from '/@/enums/cacheEnum';

// src\enums\cacheEnum.ts
export const APP_DARK_MODE_KEY_ = '__APP__DARK__MODE__'; 
export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__';

每个功能就如拼图碎片,一开始讲解起来有些有些割裂感,随着系统代码不断的深入解析, 整个拼图会逐渐清晰,让你从全局掌握整体架构脉络。