# vue3-pc-sys **Repository Path**: yuyingqianduan/vue3-pc-sys ## Basic Information - **Project Name**: vue3-pc-sys - **Description**: Vue 3 + TypeScript + Vite4/5 + Ant-design-vue4.x+ Pinia + vue-router4搭建后台系统通用骨架 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-12-21 - **Last Updated**: 2024-01-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: vue3, TypeScript, CSS, ant-design-vue, Pinia ## README # Vue 3 + TypeScript + Vite4/5 + Ant-design-vue4.x + Pinia + vue-router4 本项目采用前端最潮流技术搭建~仅供参考学习! - Vue Language Features (Volar) - TypeScript Vue Plugin (Volar) ## 前置知识 关于package.json里面,尖角号(^)和波浪线(~)的区别 - 尖角号(^)通常用于指定主要版本号不变,允许安装新的次要版本和修补程序版本 - 波浪线(~)通常用于指定包的修补程序版本不变,允许安装新的次要版本和主要版本 - /** */这种方式注释 则如果其他地方用到这个变量,鼠标放上去会有注释提示 - process.env.NODE_ENV 是node环境的变量 - 打印 process.env.NODE_ENV,值为 development 代表是开发环境,值为 production 代表是生产环境 ## 创建项目 ```shell pnpm create vite [工程名] --template vue ``` ### 重置样式表 方案一: css 重置样式表(Normalize.css)【推荐】 html 标签在浏览器中都有各自的默认样式,比如: p 标签有上下边距,strong 标签有字体加粗样式,em 标签有字体倾斜样式。不同浏览器的默认样式之间也会有差别,例如 ul 默认带有缩进的样式,在 IE 下,它的缩进是通过 margin 实现的,而 Firefox 下,它的缩进是由 padding 实现的。Normalize.css 不同浏览器默认样式的规范统一,从而提高开发效率。 - normalize.css 并不是简单的重置了所有的样式,保留标签语义化 - normalize 没有对所有标签采取一致的重置方式,而是有针对的修改,同时也保留了标签的语义化 - Normalize CSS 可以看成是一种 Reset CSS 的替代方案 ```shell pnpm install --save normalize.css ``` ```js // main.js引入 import 'normalize.css/normalize.css' ``` 方案二:重置 CSS [css reset](https://meyerweb.com/eric/tools/css/reset/) 总结:一般都是两个结合 起来处理 ### vite4 别名处理 ```shell pnpm i vite-aliases -D ``` ```ts // vite.config.ts 使用 import { ViteAliases } from 'vite-aliases' plugins: [ViteAliases()] ``` 由于 vite-aliases 插件仅支持 ESM,需要在项目根路径下的 package.json 下配置如下代码 ```json { "type": "module" } ``` ```shell pnpm i @types/node -D # 如果报错 降低版本 18.11.11 # @types/node 模块在我们使用 node 方法(比如 path.resolve)时提供 ts 类型声明,否则编辑器会报错,虽然不影响代码运行 ``` tsconfig.json 需要额外配置 ```json "baseUrl": "./", // paths安装了 vite-aliases依赖自动生成 ``` ## 采用 scss 预处理器 增加 -D 参数,在开发环境中才使用 sass,因为生产环境,scss 文件会被编译成 css 文件,这个插件是用不到的 ```shell pnpm install sass -D ``` ## 在项目的根目录,新建 .nvmrc 文件,输入初始化时 node 的版本号,用来避免每次切换项目都手动切换 node 版本 新增此文件后需要重启 vscode,打开终端会自动切换 node 版本 .nvmrc 键入 v18 ## 使用 polyfill polyfill 是 web 项目兼容低版本浏览器的插件,安装 core-js 和 @vitejs/plugin-legacy [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) ```shell pnpm i @vitejs/plugin-legacy -D pnpm i core-js -S # Terser must be installed because plugin-legacy uses Terser for minification pnpm add -D terser ``` ## 配置代码规范 ### eslint 相关 - "off" 或 0 - 关闭规则 - "warn" 或 1 - 打开规则作为警告(不影响退出代码) - "error" 或 2 - 打开规则作为错误(触发时退出代码为 1) ```shell pnpm init @eslint/config pnpm i @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-plugin-vue -D ``` 在 package.json 的 script 中添加命令 ```json "scripts": { "lint": "eslint --ext .ts,.vue,.js, --fix --quiet ./" }, ``` ### Prettier 美化格式化代码 然后再根目录创建 .prettierrc.cjs 配置文件 ```js "lint:prettier": "prettier --write \"**/*.{js,ts,json,css,less,scss,vue,html,md}\"" ``` ```shell pnpm i prettier -D pnpm i eslint-config-prettier eslint-plugin-prettier -D ``` ### ESLint + Prettier 参考配置 `pnpm eslint --init` 会自动生成 `.eslintrc.cjs` 或者 `pnpm init @eslint/config` 也会 会自动生成 ```cjs module.exports = { env: { browser: true, es2021: true }, extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:vue/vue3-essential', 'prettier', // 由于eslint和prettier都具备代码格式化的功能,并且可能出现冲突,所以继承eslint-config-prettier提供的配置,将eslint中冲突的配置项关闭了 'plugin:prettier/recommended' ], overrides: [ { env: { node: true }, files: ['.eslintrc.{js,cjs}'], parserOptions: { sourceType: 'script' } } ], parserOptions: { ecmaVersion: 'latest', parser: '@typescript-eslint/parser', sourceType: 'module' }, plugins: ['@typescript-eslint', 'vue', 'prettier'], rules: { // 开启这条规则后,会将prettier的校验规则传递给eslint,这样eslint就可以按照prettier的方式来进行代码格式的校验 'prettier/prettier': 'off', // rules中添加prettier推荐配置 // 箭头函数体周围需要大括号 'arrow-body-style': 'off', // 需要使用箭头函数进行回调 'prefer-arrow-callback': 'off', // 不允许使用未声明的变量 'no-undef': 'error', // 禁止未使用的变量 'no-unused-vars': 'error', // 禁止使用 var 'no-var': 'error', // 函数括号前的空格 'space-before-function-paren': 'off', // 关闭名称校验 'vue/multi-word-component-names': 'off', // 禁止 v-for 指令或范围属性的未使用变量定义 https://eslint.vuejs.org/rules/no-unused-vars.html 'vue/no-unused-vars': 'error', // 禁止在与 v-for 相同的元素上使用 v-if https://eslint.vuejs.org/rules/no-use-v-if-with-v-for.html 'vue/no-use-v-if-with-v-for': [ 'error', { allowUsingIterationVar: true } ], // 禁止未使用的变量 https://typescript-eslint.io/rules/no-unused-vars '@typescript-eslint/no-unused-vars': 'error', 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 解决 Don't use `{}` as a type. `{}` actually means "any non-nullish value" '@typescript-eslint/ban-types': [ 'error', { extendDefaults: true, types: { '{}': false } } ], // 解决使用 any 类型报错 '@typescript-eslint/no-explicit-any': ['off'] } } ``` ## 提交代码 使用 husky + lint-staged ```shell pnpm i husky -D pnpm i lint-staged -D # 集成 husky 和 lint-staged 在项目根目录会自动生成 .husky/pre-commit 等文件 或者 npx husky-init pnpx mrm@2 lint-staged ``` 在 .gitignore 中增加 .eslintcache 不加这个,总是卡在提交哪一步 ### 方式二 ```shell # 运行下面2条命令后也会在项目根目录创建 .husky 文件夹 pnpm pkg set scripts.prepare="husky install" pnpm run prepare # 给 Husky 添加一个 Hook npx husky add .husky/pre-commit "npm run lint" ``` ## 配置 ⽀持的浏览器 .browserslistrc 根目录 浏览器兼容性配置文件,可以配置支持那些浏览器 配置 cover 99.5% 或者 参考以下配置 > 1% last 2 versions not dead not IE 11 ## 自动修复 import 排序插件 eslint-plugin-simple-import-sort 自动修复 import 排序 ```shell pnpm i eslint-plugin-simple-import-sort -D ``` ```js // 在.eslintrc.cjs中配置 plugins:['simple-import-sort'] ``` ## 配置 EditorConfig 根目录配置 .editorconfig 文件 ## 配置 stylelint 下载相关依赖 ```shell pnpm i stylelint stylelint-config-html stylelint-config-recommended-scss stylelint-config-recommended-vue stylelint-config-standard stylelint-config-standard-scss stylelint-config-recess-order postcss postcss-html postcss-lit stylelint-config-prettier stylelint-config-tailwindcss -D ``` stylelint-config-prettier 已经弃用 v15 [参考](https://stylelint.io/migration-guide/to-15) 命令执行完成后,如若报类似下面的警告,可以先不管 `unmet peer stylelint@“>= 11.x < 15”: found 16.0.2` ## commitizen 安装自动化提示工具 安装依赖 ```shell pnpm i @commitlint/cli @commitlint/config-conventional -D # 安装自动化提示工具 pnpm i commitizen cz-conventional-changelog -D pnpm i commitlint-config-cz cz-customizable -D ``` 配置脚本命令 ```json { "scripts": { "commit": "git status && git add . && git-cz" }, } ``` 生成校验钩子 ```shell npx husky add .husky/commit-msg 'npx --no-install commitlint -e "$HUSKY_GIT_PARAMS"' ``` 初始化命令行的选项信息 执行后会在package.json生成commitizen的配置信息 ```shell npx commitizen init cz-conventional-changelog --save-dev --save-exact ``` package.json 配置 ```json // 这里存在一个不足:无法正常校验通过命令行提交的类似 commit -m 'xxx'这样的备注信息 "config": { "commitizen": { "path": "./node_modules/cz-customizable" }, "cz-customizable": { "config": ".cz-config.cjs" } } ``` ## tailwindcss 配置 ```shell pnpm install -D tailwindcss postcss autoprefixer pnpx tailwindcss init ``` ## vite多环境打包配置 根目录新建如下文件 - .env 全局默认配置文件,不论什么环境都会加载合并 - .env.development 开发环境下的配置文件 - .env.test 测试环境下的配置文件 - .env.stage 预发布环境下的配置文件 - .env.production 生产环境下的配置文件 解决 仅当 “--module” 选项为 “es2020”、“es2022”、“esnext”、“system”、“node16” 或 “nodenext” 时,才允许使用 “import.meta” 元属性。 tsconfig.json下配置 ```json "module" : "ESNext", "moduleResolution": "node", "allowSyntheticDefaultImports": true, ``` 配置打包命令 package.json scripts ```json "build:test": "vue-tsc && vite build --mode test ", "build:stage": "vue-tsc && vite build --mode stage", "build:prod": "vue-tsc && vite build --mode production", ``` ## http-server 的使用 ```shell # 安装 pnpm install http-server -g # 启动 任意一个文件夹都可以当服务器去使用 构建后我们一般在dist文件下执行 http-server # 在当前目录下的 dist 下启动服务器,端口为 3000, 启动成功后打开默认浏览器,地址为:http://localhost:3000/ http-server './dist/' -p 3000 -o ``` ## 打包分析插件 打包后,会在根目录下生成一个 stats.html文件,用浏览器打开后即可看到打包情况 ```shell pnpm install rollup-plugin-visualizer -D ``` ```ts // vite.config.js import { defineConfig } from 'vite' import { visualizer } from 'rollup-plugin-visualizer' export default defineConfig({ plugins: [visualizer()] }) ``` ## 通过监听文件修改,自动重启 vite 服务 最常用的场景就是监听 vite.config.js 和 .env.development 文件,修改 vite 配置文件和环境配置文件,是需要重启 vite 才会生效,通过这个插件,在修改上述两个文件则不需要重新运行 ```shell pnpm i vite-plugin-restart -D ``` ```ts // vite.config.js import ViteRestart from 'vite-plugin-restart' export default { plugins: [ ViteRestart({ restart: [ 'vite.config.js', ] }) ], }; ``` ## 配置pinia,并做持久化存储 ```shell pnpm i pinia -S pnpm i pinia-plugin-persist -S ``` ## 项目中 svg 统一处理 因为svg图标在任何设备下都可以高清显示,不会模糊 这就是理由 - height=“1em” width=“1em” 可以方便地通过设置父元素的font-size属性控制尺寸 - fill=“currentColor” 可以方便地根据父元素或自身的color属性控制颜色 [iconfont 阿里巴巴图表库](https://www.iconfont.cn/) ```html icon: https://www.test.com + '/icons/test.svg' ``` ```shell pnpm i vite-plugin-svg-icons -D ``` ```ts // vite.config.ts import {createSvgIconsPlugin} from 'vite-plugin-svg-icons'; import { defineConfig,loadEnv } from 'vite' import {createSvgIconsPlugin} from 'vite-plugin-svg-icons'; const path = require("path"); export default ({ mode }) => defineConfig({ plugins: [ vue(), createSvgIconsPlugin({ // 指定要缓存的文件夹 iconDirs: [resolve(process.cwd(), 'src/assets/svg')], // 指定symbolId格式 symbolId: 'icon-[dir]-[name]' }) ] }) // 更多配置说明 viteSvgIcons({ // 指定图标文件夹,数组形式,可以有多个 iconDirs: [path.resolve(process.cwd(), 'icons')], // 指定symbolId格式 symbolId: 'icon-[dir]-[name]', // 自定义插入位置 inject?: 'body-last' | 'body-first', // 设置图标样式类名 className?: 'svg-icon', // 设置svg元素属性 svgoOptions: {}, // 指定标题内容 title?: false, // 生成sprite svgSprite: false, // 导入图标接口 runtimeIconImport: 'import-all' | 'async', }) ``` ```ts // main.ts import 'virtual:svg-icons-register' ``` ```html ``` 封装 svg组件 ```html ``` svg 组件全局引入使用 ```ts // main.ts // 在main.js中加入 import svgIcon from '~components/SvgIcon/index.vue' createApp(App).component('svg-icon', svgIcon) // 页面中使用 // 控制大小 ``` 如果需要改变svg的颜色只需要把svg自带的fill去掉即可! ## setup语法糖name增强,使vue3语法糖支持name属性 vue3语法糖默认是没有name属性的,在我们使用 keep-alive 的时候需要用到 name ```shell pnpm i vite-plugin-vue-setup-extend -D ``` ```ts // vite.config.ts import { defineConfig} from 'vite' import vueSetupExtend from 'vite-plugin-vue-setup-extend' export default ({ mode }) => defineConfig({ plugins: [ vueSetupExtend() ] } // 组件使用 ``` ## 需要配置代理的情况 浏览器的同源策略限制了前端页面向不同域名的接口发起请求,这导致某些情况下需要使用代理服务器来转发请求 - 使用第三方 API 或服务:例如,使用第三方地图 API 服务,需要向 API 服务提供商的域名下的接口发起请求,而这与前端页面所在的域名不同 - 开发环境与生产环境不同:在开发环境中,前端页面通常运行在本地的开发服务器上,而后端服务则运行在远程服务器上。在这种情况下,由于开发服务器与后端服务器的域名不同,因此需要使用代理服务器将请求转发到正确的后端服务端点 - 部分接口需要登录认证:在某些情况下,服务端需要对接口进行访问控制,需要用户先在页面进行登录认证。这时,前端页面需要先向自己的域名下的登录接口发起请求进行认证,获得认证信息后,再使用代理服务器将包含认证信息的请求转发到相应的接口上 - token的校验 Authorization: 'Bearer ' + token ## 图片资源压缩 ```shell pnpm i vite-plugin-imagemin -D ``` ```ts // vite.config.ts import viteImagemin from 'vite-plugin-imagemin' plugin: [ viteImagemin({ gifsicle: { optimizationLevel: 7, interlaced: false }, optipng: { optimizationLevel: 7 }, mozjpeg: { quality: 20 }, pngquant: { quality: [0.8, 0.9], speed: 4 }, svgo: { plugins: [ { name: 'removeViewBox' }, { name: 'removeEmptyAttrs', active: false } ] } }) ] ``` ## 安装UI库 ant-design-vue [ant-design-vue官方文档](https://www.antdv.com/docs/vue/getting-started-cn) ```shell # 安装 pnpm i --save ant-design-vue@4.x ## 图标 pnpm install --save @ant-design/icons-vue # 自动按需引入组件 pnpm install unplugin-vue-components -D ``` ## 配置进度条 nprogress ```shell pnpm i nprogress -S pnpm i @types/nprogress -D ``` ## 封装 axios ```shell pnpm i axios -S pnpm i qs -S ``` ## 安装路由 ```shell pnpm add vue-router@4 #OR pnpm i vue-router@4 -S #CDN ``` ## 安装动画css animate.css 库 [animate.css 官网](https://animate.style/) ```shell pnpm install animate.css --save # 使用 animate__animated + 动画类名 ``` ## 记录问题 - Q: 类型"ImportMeta"上不存在属性"env" - A: 在tsconfig.json文件的"compilerOptions"里添加 "types": ["vite/client"] - Q: vue3有好用的hooks么 - A: 有,推荐[vueuse中文文档参考](https://www.vueusejs.com/guide/),[vueuse英文文档参考](https://vueuse.org/guide/) - Q: 有时候 node_modules 删不掉什么办法强制移除node_modules - A: 当前项目执行 Remove-item -Force -Recurse node_modules 即可快速删除 或者 安装`npm install rimraf -g` 执行名,rimraf node_modules - Q: 规则@tailwind css未知(unknownAtRules) - A: .vscode 文件夹下 配置 settings.json:`"files.associations": { "*.css": "tailwindcss"}` 即可解决 - Q: vue3使用scss ::v-deep深度选择器抛出如下警告:`usage as a combinator has been deprecated. Use :deep() instead.` - A: :deep(.xxx选择器/类名){} 即可解决 - Q: TS 去写项目代码一个没有类型声明的 npm 包 / 模块的时候 `Cannot find module or its corresponding type declarations` - A: 方式一粗暴:注释TS检测 @ts-ignore,方式二:新建一个 XXX.d.ts 文件 declare module 'xxxx' - Q: a-form-item 使用prop 校验控制台报错 `prop` is deprecated. Please use `name` instead. - A: 按照推荐使用 name 即可 无需prop - Q: async await 报错 `Property 'result' does not exist on type 'AxiosResponse'` - A: 代码如下拓展出来对应的属性即可 ```js declare module 'axios' { interface AxiosResponse { // 这个地方为AxiosResponse添加扩展属性 code: number result: string message: string | undefined | null data: T } } ```