5

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

 2 years ago
source link: https://www.cnblogs.com/anduril/p/16326845.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK