# 一、依赖管理   本项目会传递安装的依赖有: | 包名称 | 版本 | 含义和用途说明 | |-------|------|---------------| | `@fortawesome/fontawesome-free` | ^6.7.2 | FontAwesome 图标库的免费版本 | | `@popperjs/core` | ^2.11.8 | 工具提示和弹出框定位引擎 | | `axios` | ^1.4.0 | 基于 Promise 的 HTTP 客户端 | | `compressorjs` | ^1.2.1 | 纯 JavaScript 图片压缩库 | | `crypto-js` | ^4.2.0 | JavaScript 加密算法库 | | `dayjs` | ^1.11.13 | 轻量级的日期处理库 | | `echarts` | ^5.5.1 | 百度开源的数据可视化图表库 | | `element-plus` | ^2.6.0 | 基于 Vue 3 的桌面端 UI 组件库 | | `js-cookie` | ^3.0.5 | JavaScript Cookie 操作库 | | `lunar-calendar` | ^0.1.4 | 农历日历转换库 | | `lunar-javascript` | ^1.6.13 | 农历日期处理的 JavaScript 库 | | `path-browserify` | ^1.0.1 | Node.js path 模块的浏览器版本兼容实现 | | `qs` | ^6.13.0 | URL 查询字符串解析和序列化库 | | `v-calendar` | ^3.1.2 | Vue.js 的日历和日期选择器组件 | ::: tip 如果使用pnpm安装,会传递peerDependencies部分。 ::: ::: warning 建议将Vite、Typescript、@types等构建工具依赖放在devDependencies中。 ::: # 二、vite.config.ts配置 ## 2.1 生成Typescript类型文件   安装vite-plugin-dts插件 ```cmd pnpm add vite-plugin-dts -D ``` ```typescript import dts from 'vite-plugin-dts' // 打包输出文件夹 const outDirPath = 'dist' // 需要打包的类型文件 const TARGET_TYPE_FOLDERS = ['src/components', 'src/utils', 'src/types', 'src/vue3-common.ts'] export default defineConfig({ plugins: [ // 生成类型文件 dts({ // 需要处理的文件 include: TARGET_TYPE_FOLDERS, // 使用特定的 tsconfig 配置 tsconfigPath: path.resolve(__dirname, 'tsconfig.app.json'), // 类型文件输出目录 outDir: path.resolve(__dirname, outDirPath) }) ], }) ```   打包后会在dist目录生成.d.ts文件,提供完整的Typescript类型支持。 ## 2.2 build打包配置 ```typescript import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import dts from 'vite-plugin-dts' import path from 'path' import fs from 'fs' import { ICommonObj } from './src/types' // 打包输出文件夹 const outDirPath = 'dist' // 需要单个打包的文件夹(组件和工具类) const TARGET_LIB_FOLDERS = ['src/components', 'src/utils'] // 需要排除的第三方依赖 const EXTERNAL = ['vue', 'element-plus', 'echarts', 'axios', 'moment', 'crypto-js', 'spark-md5', 'path-browserify'] /** * 递归读取文件夹下的所有文件 * @param folderPath 文件夹 */ const getFilesFromFolder = (folderPath: string) => { const files: string[] = [] // 读取文件夹中的内容 fs.readdirSync(folderPath).forEach((item: string) => { const fullPath = path.join(folderPath, item) // 读取文件状态 如果是文件夹,递归读取 if (fs.statSync(fullPath).isDirectory()) { files.push(...getFilesFromFolder(fullPath)) } else { // 否则添加至文件列表 files.push(fullPath) } }) return files } // 动态生成入口文件 const inputEntries = TARGET_LIB_FOLDERS.reduce((entries: ICommonObj, folder) => { // 获取文件夹内的所有文件 const files = getFilesFromFolder(path.resolve(__dirname, folder)) files.forEach((filePath) => { // 判断文件是否是 .vue 或 .ts 文件 if (filePath.endsWith('.vue') || filePath.endsWith('.ts')) { // 获取相对路径并保持目录结构 const relativePath = path.relative('src', filePath) const entryName = path.join('lib', relativePath.replace(/\.(vue|ts)$/, '')) entries[entryName] = filePath // 为每个文件创建一个入口 } }) return entries }, {}) // https://vitejs.dev/config/ export default defineConfig({ build: { // lib文件配置 lib: { // 入口文件 entry: path.resolve(__dirname, 'src/vue3-common.ts'), formats: ['es'], name: 'vue3-common', // 文件名 fileName: (format) => `vue3-common.${format}.js` }, // 输出文件路径 outDir: outDirPath, // 是否将css文件分割 cssCodeSplit: true, // Rollup打包配置 rollupOptions: { // 需要排除的依赖 通常为第三方库 external: EXTERNAL, // 输入配置 input: { // 入口文件 'vue3-common': path.resolve(__dirname, 'src/vue3-common.ts'), // 其余需要单独打包的文件 ...inputEntries }, // 输出配置 output: { dir: path.resolve(__dirname, outDirPath), // 入口文件 entryFileNames: '[name].js', // chunk文件 chunkFileNames: 'lib/[name].js', // 资源文件 assetFileNames: 'styles/[name].[ext]' } }, // 是否压缩代码 minify: false } }) ```   打包后会在dist目录生成源码文件。 # 三、package.json配置 ## 3.1 导出路径 ```json { "exports": { ".": { "import": "./dist/vue3-common.js", "require": "./dist/vue3-common.js", "types": "./dist/vue3-common.d.ts" }, "./components/SvgIcon.vue": { "import": "./dist/lib/components/SvgIcon.js", "types": "./dist/components/SvgIcon.vue.d.ts" }, "./styles/SvgIcon.css": "./dist/styles/SvgIcon.css", "./components/LoginForm.vue": { "import": "./dist/lib/components/LoginForm.js", "types": "./dist/components/LoginForm.vue.d.ts" }, "./styles/LoginForm.css": "./dist/styles/LoginForm.css", "./components/MenuItem.vue": { "import": "./dist/lib/components/MenuItem.js", "types": "./dist/components/MenuItem.vue.d.ts" }, "./components/MenuList.vue": { "import": "./dist/lib/components/MenuList.js", "types": "./dist/components/MenuList.vue.d.ts" }, "./components/Hamburger.vue": { "import": "./dist/lib/components/Hamburger.js", "types": "./dist/components/Hamburger.vue.d.ts" }, "./styles/Hamburger.css": "./dist/styles/Hamburger.css", "./components/MultiInput.vue": { "import": "./dist/lib/components/MultiInput.js", "types": "./dist/components/MultiInput.vue.d.ts" }, "./styles/MultiInput.css": "./dist/styles/MultiInput.css", "./types": { "types": "./dist/types/index.d.ts" }, "./utils/axiosUtil": { "import": "./dist/lib/utils/axiosUtil.js", "types": "./dist/types/utils/axiosUtil.d.ts" }, "./utils/cryptoUtil": { "import": "./dist/lib/utils/cryptoUtil.js", "types": "./dist/types/utils/cryptoUtil.d.ts" }, "./utils/dataUtil": { "import": "./dist/lib/utils/dataUtil.js", "types": "./dist/types/utils/dataUtil.d.ts" }, } } ```   在项目中引入common包后,通过配置tsconfig.json即可实现按需引入功能`import { fun1 } from 'vue3-common/utils/index'`。 ```json { "compilerOptions": { "baseUrl": ".", "paths": { "vue3-common/*": ["node_modules/vue3-common/dist/*"] } } } ``` # 四、发布框架 1. 发布到本地 执行`npm pack`命令,会在项目文件夹下生成`.tgz`文件,其他项目通过文件路径形式引入: ```json "vue3-common": "file:../vue3-common/vue3-common-1.0.0.tgz" ``` 2. 发布到git 将dist文件夹发布到git仓库,其他项目通过git形式引入: ```json "vue3-common": "git+https://gitee.com/Cxx0822/vue3-common#master" ``` # 五、组件使用说明 ## 5.1 菜单组件 1. 安装Vue Router ```cmd pnpm install vue-router ``` 2. 在src/views文件夹中新建vue文件,例如: ```cmd views viewA index.vue viewB index.vue ``` 3. 在src/views文件夹下新建meta.ts配置文件 ```typescript import type { IRouteMetaConfig } from 'vue3-common/types' export const metaList: IRouteMetaConfig = { '/viewA': { title: 'viewA', icon: 'viewA', order: 1, redirect: '/viewA/index' }, '/viewA/index': { title: 'viewA-Index', icon: '' }, '/viewB': { title: 'viewB', icon: 'viewB', order: 2, redirect: '/viewB/index' }, '/viewB/index': { title: 'viewB-index', icon: '' } } ```   order对应的显示顺序关系,icon对应的为src/icons/svg中的svg图标文件(参考下文图标组件)。 4. 在src目录新建router文件夹,新建menu.ts文件 ```typescript import { getRoutersByModules, sortRoutesByOrder } from 'vue3-common/utils/routerUtil' import Layout from '@/layout/index.vue' import { metaList } from '@/views/meta' const modules = { ...import.meta.glob('@/views/viewA/**/*.vue'), ...import.meta.glob('@/views/viewB/**/*.vue'), } const menuRoutes = getRoutersByModules(modules, Layout, metaList) export default sortRoutesByOrder(menuRoutes) ```   导入刚才的views文件夹并生成路由菜单。 5. 如果还有其他的常量路由,可以在src/router中新建constant.ts文件: ```typescript import type { RouteRecordRaw } from 'vue-router' const constantRoutes: RouteRecordRaw[] = [ { path: '/', redirect: '/login' }, // 主页 { path: '/login', component: () => import('@/views/login/index.vue'), meta: { hidden: true } } ] export default constantRoutes ```   该部分即Vue Router中的路由定义。 6. 在src/router中新建index.ts: ```typescript import { createRouter, createWebHashHistory } from 'vue-router' import type { RouteRecordRaw } from 'vue-router' import { setupRouteGuard } from 'vue3-common/utils/permissionUtil' // 使用 import.meta.glob 自动导入所有 src/router 目录下的 .ts 文件 const routeModules = import.meta.glob('./*.ts', { eager: true }) // 将所有模块的默认导出(即路由配置)合并成一个路由数组 const routes: RouteRecordRaw[] = Object.values(routeModules) .map((module: any) => module.default) // 获取每个模块的默认导出 .flat() // 扁平化数组,确保所有路由项都在一个数组中 const router = createRouter({ history: createWebHashHistory(), scrollBehavior: () => ({ top: 0 }), routes }) // 设置路由守卫 setupRouteGuard(router) export default router ```   遍历src/router文件夹下所有的路由文件,并添加路由守卫。 7. 在main.ts中配置路由: ```ts // 引入路由 import router from './router' // 创建Vue3实例 const app = createApp(App) // 使用路由 app.use(router) ``` ## 5.2 图标组件 1. 安装vite-plugin-svg-icons依赖 ```cmd pnpm install vite-plugin-svg-icons -D ``` 2. 配置vite.config.ts ```typescript import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' export default defineConfig({ plugins: [ vue(), createSvgIconsPlugin({ // 指定 SVG图标 保存的文件夹路径 iconDirs: [path.resolve(process.cwd(), 'src/icons/svg')], // 指定 使用svg图标的格式 symbolId: 'icon-[dir]-[name]' }) ], }) ``` 3. 在main.ts中注册 ```typescript // 注册svg-icon import 'virtual:svg-icons-register' ``` 4. 在src/icons/svg目录中添加svg图标 5. 在组件中使用 ```vue ```