• Vben Admin 源码学习:项目初始化


    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();
    }
    

    👋👋 本文主要概述了项目实例创建时初始化的流程,接下来我们将逐一分析每个模块的功能。

  • 相关阅读:
    FPGA工程师面试试题集锦31~40
    机器学习课后习题 --- 朴素贝叶斯
    SecretFlow学习指南(2)学习路径
    在antd-table新增索引列
    HTML旅游景点网页作业制作——旅游中国11个页面(HTML+CSS+JavaScript)
    【Auth Proxy】为你的 Web 服务上把锁
    论文翻译:2021_A New Real-Time Noise Suppression Algorithm for Far-Field Speech Communication Based on Recurrent Neural Network
    【算法|动态规划No.10】leetcode LCR 089. 打家劫舍 & LCR 090. 打家劫舍 II
    如何使用CSS实现一个带有动画效果的折叠面板(Accordion)?
    FastestDet---模型训练
  • 原文地址:https://www.cnblogs.com/anduril/p/16326845.html