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
srcstoreindex.ts
文件中声明 setupStore
方法,用于将创建一个 pinia 根存储并注册到应用程序中。
... import { createPinia } from 'pinia'; // 创建一个 pinia(根存储) const store = createPinia(); export function setupStore(app: App<Element>) { // 注册到应用程序 app.use(store); }
initAppConfigStore
srclogicsinitAppConfig.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
srccomponentsregisterGlobComp.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
srclocalessetupI18n.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
srcrouterindex.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
srcrouterguardindex.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
srclogicserror-handleindex.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(); }
👋👋 本文主要概述了项目实例创建时初始化的流程,接下来我们将逐一分析每个模块的功能。