1. 程式人生 > 其它 >Vben Admin 原始碼學習:狀態管理-專案配置

Vben Admin 原始碼學習:狀態管理-專案配置

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__';

每個功能就如拼圖碎片,一開始講解起來有些有些割裂感,隨著系統程式碼不斷的深入解析, 整個拼圖會逐漸清晰,讓你從全域性掌握整體架構脈絡。