Vben Admin 源碼學習:項目初始化
- 2022 年 5 月 30 日
- 筆記
- 0x02.FrontEnd, vben-admin, VUE
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();
}
👋👋 本文主要概述了項目實例創建時初始化的流程,接下來我們將逐一分析每個模組的功能。