Vben Admin 原始碼學習:專案初始化

Anduril發表於2022-05-30

0x00 前言

Vue-Vben-Admin 是一個免費開源的中後臺模版。使用了最新的vue3,vite2,TypeScript等主流技術開發,開箱即用的中後臺前端解決方案考。

本系列本著學習參考的目的,對專案程式碼進行深入分析 ,耐心讀完,相信您會有所收穫。

本系列需要一定的專案使用經驗,建議先閱讀專案的 中文文件 ,會對理解非常有幫助。

0x.01 ?目錄說明

專案主要目錄結構及說明,接下來將一一深入分析介紹。

.
├── build # 打包指令碼相關
├── mock # mock資料夾
├── public # 公共靜態資源目錄
├── src # 主目錄
│   ├── api # 介面檔案
│   ├── assets # 資原始檔
│   ├── components # 公共元件
│   ├── design # 樣式檔案
│   ├── directives # 指令
│   ├── enums # 列舉/常量
│   ├── hooks # hook
│   ├── layouts # 佈局檔案
│   ├── locales # 多語言
│   ├── logics # 邏輯
│   ├── main.ts # 主入口
│   ├── router # 路由配置
│   ├── settings # 專案配置
│   ├── store # 資料倉儲
│   ├── utils # 工具類
│   └── views # 頁面
├── test # 測試
├── types # 型別檔案
├── vite.config.ts # vite配置檔案
└── windi.config.ts # windcss配置檔案

0x.02 ? 系統主入口

檔案 src/main.ts 作為系統主入口,主要進行專案初始化操作。

在入口檔案中引入windicss,這樣專案中就可以使用 [類實用程式] 或 [CSS 指令]。
同時引入專案中使用的通用樣式,都存放於 src/design/ 下面,預設使用 less 作為預處理語言。

import 'virtual:windi-base.css';
import 'virtual:windi-components.css';
import '/@/design/index.less';
import 'virtual:windi-utilities.css';
// Register icon sprite
import 'virtual:svg-icons-register';

windcss 目前會造成本地開發記憶體溢位,所以後續可能會考慮切換到 TailwindCss 。

接下來執行 bootstrap 方法建立專案實列。

import App from './App.vue';
import { createApp } from 'vue';
import { initAppConfigStore } from '/@/logics/initAppConfig';
import { setupErrorHandle } from '/@/logics/error-handle';
import { router, setupRouter } from '/@/router';
import { setupRouterGuard } from '/@/router/guard';
import { setupStore } from '/@/store';
import { setupGlobDirectives } from '/@/directives';
import { setupI18n } from '/@/locales/setupI18n';
import { registerGlobComp } from '/@/components/registerGlobComp';

// 專案的初始化配置
async function bootstrap() {
  // 建立應用例項
  const app = createApp(App);
  // 配置儲存使用Pinia
  setupStore(app);
  // 初始化內部系統配置
  initAppConfigStore();
  // 註冊全域性元件
  registerGlobComp(app);
  // 多語言配置
  await setupI18n(app);
  // 配置路由
  setupRouter(app);
  // 路由守衛、許可權判斷、初始化快取資料
  setupRouterGuard(router);
  // 註冊全域性指令
  setupGlobDirectives(app);
  // 配置全域性錯誤處理
  setupErrorHandle(app);
  ...    
  
  app.mount('#app');
}
bootstrap();

bootstrap() 執行時呼叫了很多方法用於初始化操作,包括配置儲存、載入系統配置註冊、註冊全域性元件、多語言配置、路由配置、路由守衛、許可權過濾、註冊全域性指令等。接下來將快速概覽下各方法:

setupStore

src\store\index.ts 檔案中宣告 setupStore 方法,用於將建立一個 pinia 根儲存並註冊到應用程式中。

...
import { createPinia } from 'pinia'; 
// 建立一個 pinia(根儲存)
const store = createPinia(); 
export function setupStore(app: App<Element>) {
  // 註冊到應用程式
  app.use(store);
}

initAppConfigStore

src\logics\initAppConfig.ts 檔案中宣告 initAppConfigStore 方法,用於載入並儲存 國際化、主題風格、專案配置、頁面載入、頁面狀態、頂欄配置、選單配置等專案資訊。

export function initAppConfigStore() {
  const localeStore = useLocaleStore(); // 多語言國際化
  const appStore = useAppStore(); // 應用狀態(主題風格、專案配置、頁面載入、頁面狀態等等)
  // 專案配置 (主題顏色、主題模式、頂欄配置、選單配置)
  let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig;
  projCfg = deepMerge(projectSetting, projCfg || {});
  ...
 
  // 儲存專案配置
  appStore.setProjectConfig(projCfg);

  // init dark mode  初始化暗黑模式
  updateDarkTheme(darkMode);
  if (darkMode === ThemeEnum.DARK) {
     ...
  } else {
    ...
  }
  // init store  初始化國際化多語言
  localeStore.initLocale();

  // 清理過期的快取
  setTimeout(() => {
    clearObsoleteStorage();
  }, 16);
}

registerGlobComp

src\components\registerGlobComp.ts檔案中宣告 registerGlobComp 方法,全域性註冊 antdv的Input、Layout元件和手寫的Button元件

import { Button } from './Button';
import { Input, Layout } from 'ant-design-vue';

export function registerGlobComp(app: App) {
  // 註冊 antdv的Input、Layout元件和手寫的Button元件
  app.use(Input).use(Button).use(Layout);
}

setupI18n

src\locales\setupI18n.ts 檔案中宣告 setupI18n 方法,初始化國際化外掛 vue-i18n 例項並註冊到應用程式中。

// 國際化外掛 vue-i18n 配置項
async function createI18nOptions(): Promise<I18nOptions> {
  const localeStore = useLocaleStoreWithOut(); // 國際化本地儲存
  const locale = localeStore.getLocale; // 語言環境/當前語言
  const defaultLocal = await import(`./lang/${locale}.ts`); // 從伺服器端獲取語言翻譯檔案
  const message = defaultLocal.default?.message ?? {}; // 本地化的語言環境資訊
  ...

  return {
    legacy: false,
    locale, // 語言環境
    fallbackLocale: fallback, // 預設的語言環境
    // 本地化的語言環境資訊
    messages: {
      [locale]: message,
    },
    availableLocales: availableLocales, // 以詞法順序排列的 messages 中的可用語言環境列表
    sync: true, // 是否將根級別語言環境與元件本地化語言環境同步。 如果為 false,則無論根級別語言環境如何,都要為每個元件語言環境進行本地化。
    silentTranslationWarn: true, // true - warning off  是否取消本地化失敗時輸出的警告。如果為 true,則禁止本地化失敗警告。
    missingWarn: false,
    silentFallbackWarn: true, // 是否在回退到 fallbackLocale 或 root 時取消警告。如果為 true,則僅在根本沒有可用的轉換時生成警告,而不是在回退時。
  };
}

// 初始化國際化例項
export async function setupI18n(app: App) {
  // 獲取國際化外掛 vue-i18n 配置項
  const options = await createI18nOptions();
  i18n = createI18n(options) as I18n;
  app.use(i18n);
}

setupRouter

src\router\index.ts 檔案中宣告 setupRouter 方法,建立路由例項,載入初始路由列表,註冊到應用程式中。

// app router  建立路由例項
export const router = createRouter({
  history: createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH), // 基於 hash 的歷史記錄
  routes: basicRoutes as unknown as RouteRecordRaw[], // 新增到路由的初始路由列表 
  scrollBehavior: () => ({ left: 0, top: 0 }), // 在頁面之間導航時控制滾動的函式
});


// 註冊路由
export function setupRouter(app: App<Element>) {
  app.use(router);
}

setupRouterGuard

src\router\guard\index.ts 檔案中宣告 setupRouterGuard 方法,建立了處理頁面載入狀態、路由切換、頁面頂部進度條、許可權驗證、選單及系統狀態等守衛。

export function setupRouterGuard(router: Router) {
  createPageGuard(router); // 處理頁面狀態
  createPageLoadingGuard(router); // 處理頁面載入狀態
  createHttpGuard(router); // 路由切換時關閉當前頁面完成請求
  createScrollGuard(router); // 路由切換回到頂部
  createMessageGuard(router); // 路由切換時關閉訊息例項
  createProgressGuard(router); // 頁面頂部進度條
  createPermissionGuard(router); // 路由切換時許可權驗證
  createParamMenuGuard(router); // 選單守衛  
  createStateGuard(router); // 系統狀態守衛- 當使用者未登入時,進入登入頁面並清除儲存中的認證資訊
}

setupErrorHandle

src\logics\error-handle\index.ts 檔案中宣告 setupErrorHandle 方法,配置全域性錯誤處理,用於監控Vue異常、指令碼錯誤、promise 異常、 靜態資源異常等。

/**
 * Configure global error handling  配置全域性錯誤處理
 * @param app
 */
export function setupErrorHandle(app: App) {
  const { useErrorHandle } = projectSetting;
  if (!useErrorHandle) {
    return;
  }
  // Vue exception monitoring; Vue異常監控
  app.config.errorHandler = vueErrorHandler;

  // script error   指令碼錯誤監控
  window.onerror = scriptErrorHandler;

  //  promise exception  promise 異常監控
  registerPromiseErrorHandler();

  // Static resource exception  靜態資源異常監控
  registerResourceErrorHandler();
}

?? 本文主要概述了專案例項建立時初始化的流程,接下來我們將逐一分析每個模組的功能。

相關文章