Vscode: 前端人必备写码神器Chrome:对开发者非常友好的浏览器 (反正我是很依赖它的)Nodejs&npm:配置本地开发环境,安装 Node 后你会发现 npm 也会一起安装下来Vue.js devtools:浏览器调试插件Vue Language Features (Volar):Vscode 开发 vue3 必备插件,提供语法高亮提示,非常好用Vue 3 Snippets:vue3 快捷输入
1. 使用 vite 快速创建脚手架
兼容性注意: Vite 需要
Node.js版本>= 12.0.0。
npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app — —template vue
yarn
yarn create vite my-vue-app —template vue
pnpm
pnpm create vite my-vue-app — —template vue
这里我采用 `yarn` 来安装```bashyarn create vite try-vite-vue-app -- --template vue-ts

第二步: cd 到项目文件夹, 安装依赖, 启动项目
# 进入项目文件夹cd try-vite-vue-app# 安装依赖yarn# 启动yarn dev

2. Vite 常用基础配置
resolve.alias 配置文件引用路径别名
在我们项目开发过程中,会有很多嵌套层级的目录,所以要找到某个目录经常用相对路径../../..,层级一多就显得眼花缭乱,通过 alias 别名,我们可以快速地指定首层的目录,并且相比相对路径减少了路径索引的消耗,在性能上来说也是更优解。
import { defineConfig } from "vite";import vue from "@vitejs/plugin-vue";// 指定解析路径import { resolve } from 'path'const pathResolve = (dir: string) => resolve(__dirname, dir)// 可以是一个对象resolve: {alias: {'@': pathResolve('src'), // 设置 `@` 指向 `src` 目录views: pathResolve('src/views'), // 设置 `views` 指向 `./src/views` 目录,下同components: pathResolve('src/components'),assets: pathResolve('src/assets')}},// 也可以是一个 { find, replacement } 的数组resolve: {alias: [// /@/xxxx => src/xxxx{find: /\/@\//,replacement: pathResolve('src') + '/',},// /#/xxxx => types/xxxx{find: /\/#\//,replacement: pathResolve('types') + '/',},],},
指定解析路径使用的 path module 需要先安装nodejs的类型声明 @types/node
开发服务器选项 serve
当我们在没有任何配置的时候,在运行服务的时候,vite 是会自动跑在本地的3000端口,所以我们可以扩展下配置
server: {port: 4000, // 设置服务启动端口号,如果端口已经被使用,Vite 会自动尝试下一个可用的端口open: true, // boolean | string 设置服务启动时是否自动打开浏览器,当此值为字符串时,会被用作 URL 的路径名cors: true, // 为开发服务器配置 CORS,配置为允许跨域// 设置代理,根据我们项目实际情况配置proxy: {'/api': {target: 'http://127.0.0.1:8000', // 后台服务地址changeOrigin: true, // 是否允许不同源secure: false, // 支持httpsrewrite: path => path.replace(/^/api/, '')}}}
构建选项 build
build: {outDir: 'dist', // 指定打包路径,默认为项目根目录下的 dist 目录terserOptions: {compress: {keep_infinity: true, // 防止 Infinity 被压缩成 1/0,这可能会导致 Chrome 上的性能问题drop_console: true, // 生产环境去除 consoledrop_debugger: true // 生产环境去除 debugger},},chunkSizeWarningLimit: 1500 // chunk 大小警告的限制(以 kbs 为单位)}
3. TypeScript 配置
3.1. tsconfig.json 配置项
在初始化 vite 项目的时候可以看到,项目根目录下生成了 tsconfig.json 和 tsconfig.node.json 两个文件。
tsconfig.json 指定了用来编译这个项目的根文件和编译选项
{"compilerOptions": {"target": "esnext","useDefineForClassFields": true,"module": "esnext","moduleResolution": "node","strict": true,"jsx": "preserve","sourceMap": true,"resolveJsonModule": true,"esModuleInterop": true,"lib": ["esnext", "dom"]},"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],"references": [{ "path": "./tsconfig.node.json" }]}
可以看到tsconfig.node.json中的"include": ["vite.config.ts"]表明这个单独拆分出来的配置文件只是负责编译 vite 的配置文件vite.config.ts
{"compilerOptions": {"composite": true,"module": "esnext","moduleResolution": "node"},"include": ["vite.config.ts"]}
include 指定需要编译的文件范围
默认是对 src 下的.ts、.d.ts、.tsx、.vue结尾的文件都需要进行编译
exclude 配置不需要编译的文件范围
"exclude": ["node_modules","dist"]
references 将 TypeScript 程序拆分
属性是 TypeScript 3.0 的新特性,允许将 TypeScript 程序拆分结构化。这和我们写 vue 组件的思想有着异曲同工之妙,避免了在一个文件中处理过多的内容,而是通过拆分成多个文件,分别配置不同的部分,达到更加清晰,可维护性更高的目的。
compilerOptions 编译选项
skipLibCheck 忽略声明文件检查
忽略所有的声明文件( *.d.ts)的类型检查
"compilerOptions": {"skipLibCheck": true}
这个属性不但可以忽略 npm 不规范带来的报错,还能最大限度的支持类型系统。设置为 true 就不用怕使用的第三方库不规范了。
可能有人好奇,为什么要跳过这些第三方库的检查?
我们做类型检查(以及代码规范等)的目的是为了对团队内业务代码开发保持统一和规范,以保证开发成员之间的快速上手和后续维护。所以我们要做的是将各种规则集成到业务代码模块,而一些框架上的或者第三方库的内容就不用多此一举了。
baseUrl
作用:设置baseUrl来告诉编译器到哪里去查找模块。所有非相对模块导入都会被当做相对于 baseUrl。
注意相对模块的导入不会被设置的baseUrl所影响,因为它们总是相对于导入它们的文件.
这个设置的作用和 vite 构建选项 build 中的 base 是类似的,我们配置为当前根目录即可
paths 路径映射列表
作用:模块名到基于baseUrl的路径映射的列表。
请注意"paths"是相对于"baseUrl"进行解析。
在 vite 配置中设置了路径别名resolve.alias,为了让编译 ts 时也能够解析对应的路径,我们还需要配置 paths 选项
"paths": {"@/*": ["src/*"],"views/*": ["src/views/*"],"components/*": ["src/components/*"],"assets/*": ["src/assets/*"],"api/*": ["src/api/*"],"utils/*": ["src/utils/*"],}
isolatedModules 将每个文件作为单独模块
typescript 将没有导入/导出的文件视为旧脚本文件。因为这样的文件不是模块和它们在全局命名空间中合并的任何定义。该配置项会禁止此类文件。将任何导入或导出添加的文件都视为模块
这个设置在 vite 官方文档中是被要求应该设置为 true 的,但项目初始化的时候并没有默认加上这条
"isolatedModules": true,

https://vitejs.cn/guide/features.html#typescript-compiler-options
types 客户端类型
作用:添加要包含的类型声明文件名列表,只有在这里列出的模块的声明文件才会被加载进来
{"compilerOptions": {"types": ["vite/client"]}}
这将会提供以下类型定义补充:
- 资源导入 (例如:导入一个 .svg 文件)
- import.meta.env 上 Vite 注入的环境变量的类型定义
- import.meta.hot 上的 HMR API 类型定义
tsconfig.json 完整配置内容
{"compilerOptions": {"target": "esnext","isolatedModules": true,"useDefineForClassFields": true,"module": "esnext","moduleResolution": "node","strict": true,"jsx": "preserve","sourceMap": true,"resolveJsonModule": true,"esModuleInterop": true,"skipLibCheck": false, // 忽略所有的声明文件( *.d.ts)的类型检查,跳过第三方库的类型检查"lib": ["esnext","dom"],"baseUrl": ".","types": ["vite/client"],"paths": {"@/": ["src/"]}},"include": ["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"],"exclude": ["node_modules","dist"],"references": [{"path": "./tsconfig.node.json"}]}
3.2. env.d.ts 全局类型声明
打开 src 文件夹下的 env.d.ts文件,可以看到
/// <reference types="vite/client" />declare module '*.vue' {import type { DefineComponent } from 'vue'// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-typesconst component: DefineComponent<{}, {}, any>export default component}

请注意:三斜杠指令是包含单个XML标签的单行注释,注释的内容会做为编译器指令使用,只有在文件的最顶部才会生效,可以查看TypeScript: Documentation - Triple-Slash Directives学习相关内容。
所以这个文件的作用就呼之欲出了:帮助编译器识别类型。
TypeScript 相比 JavaScript 增加了类型声明。原则上,TypeScript 需要做到先声明后使用。这就导致开发者在调用很多原生接口(浏览器、Node.js)或者第三方模块的时候,因为某些全局变量或者对象的方法并没有声明过,导致编译器的类型检查失败。
当我们遇上Property xxx does not exist on type …报错的时候,就可以定位到是没有声明过这个方法/属性。我们就可以在这个文件作全局声明。
可以看到,该文件已经默认为所有的 vue 文件声明了 DefineComponent的组件类型,这就意味着只要我们的单文件组件使用
<script lang="ts">import { defineComponent } from 'vue'export default defineComponent({...})</script>
的写法,就能避免 vue 文件中大多数类型声明的报错,比如使用路由的this.$router、this.$route命令
eslint + prettier 约束代码风格
Eslint 支持
安装
# 1. eslint 安装yarn add eslint --dev# 2. typescript parser ESLint 默认使用的是 Espree 进行语法解析,所以无法对部分 typescript 语法进行解析,因此我么还需要安装 @typescript-eslint/parser 替换掉默认的解析器yarn add @typescript-eslint/parser --dev# 3. eslint 插件安装# 借用这个 plugin 的能力才能让 eslint 识别 vue 文件yarn add eslint-plugin-vue --dev# eslint-plugin 作为 eslint 默认规则的补充,提供了一些额外的适用于 ts 语法的规则yarn add @typescript-eslint/eslint-plugin --dev
注意: 如果 eslint 安装报错:
可以尝试运行以下命令:
yarn config set ignore-engines true
运行成功后再次执行 eslint 安装命令
1. 项目下新建 .eslintrc.js
配置
eslint校验规则:
module.exports = {root: true,env: {browser: true,node: true,es2021: true,},parser: 'vue-eslint-parser',extends: ['eslint:recommended','plugin:vue/vue3-recommended','plugin:@typescript-eslint/recommended','plugin:prettier/recommended',// eslint-config-prettier 的缩写'prettier',],parserOptions: {ecmaVersion: 12,parser: '@typescript-eslint/parser',sourceType: 'module',ecmaFeatures: {jsx: true,},},// eslint-plugin-vue @typescript-eslint/eslint-plugin eslint-plugin-prettier的缩写plugins: ['vue', '@typescript-eslint', 'prettier'],rules: {'@typescript-eslint/ban-ts-ignore': 'off','@typescript-eslint/no-unused-vars': 'off','@typescript-eslint/explicit-function-return-type': 'off','@typescript-eslint/no-explicit-any': 'off','@typescript-eslint/no-var-requires': 'off','@typescript-eslint/no-empty-function': 'off','@typescript-eslint/no-use-before-define': 'off','@typescript-eslint/ban-ts-comment': 'off','@typescript-eslint/ban-types': 'off','@typescript-eslint/no-non-null-assertion': 'off','@typescript-eslint/explicit-module-boundary-types': 'off','no-var': 'error','prettier/prettier': 'error',// 禁止出现console'no-console': 'warn',// 禁用debugger'no-debugger': 'warn',// 禁止出现重复的 case 标签'no-duplicate-case': 'warn',// 禁止出现空语句块'no-empty': 'warn',// 禁止不必要的括号'no-extra-parens': 'off',// 禁止对 function 声明重新赋值'no-func-assign': 'warn',// 禁止在 return、throw、continue 和 break 语句之后出现不可达代码'no-unreachable': 'warn',// 强制所有控制语句使用一致的括号风格curly: 'warn',// 要求 switch 语句中有 default 分支'default-case': 'warn',// 强制尽可能地使用点号'dot-notation': 'warn',// 要求使用 === 和 !==eqeqeq: 'warn',// 禁止 if 语句中 return 语句之后有 else 块'no-else-return': 'warn',// 禁止出现空函数'no-empty-function': 'warn',// 禁用不必要的嵌套块'no-lone-blocks': 'warn',// 禁止使用多个空格'no-multi-spaces': 'warn',// 禁止多次声明同一变量'no-redeclare': 'warn',// 禁止在 return 语句中使用赋值语句'no-return-assign': 'warn',// 禁用不必要的 return await'no-return-await': 'warn',// 禁止自我赋值'no-self-assign': 'warn',// 禁止自身比较'no-self-compare': 'warn',// 禁止不必要的 catch 子句'no-useless-catch': 'warn',// 禁止多余的 return 语句'no-useless-return': 'warn',// 禁止变量声明与外层作用域的变量同名'no-shadow': 'off',// 允许delete变量'no-delete-var': 'off',// 强制数组方括号中使用一致的空格'array-bracket-spacing': 'warn',// 强制在代码块中使用一致的大括号风格'brace-style': 'warn',// 强制使用骆驼拼写法命名约定camelcase: 'warn',// 强制使用一致的缩进indent: 'off',// 强制在 JSX 属性中一致地使用双引号或单引号// 'jsx-quotes': 'warn',// 强制可嵌套的块的最大深度4'max-depth': 'warn',// 强制最大行数 300// "max-lines": ["warn", { "max": 1200 }],// 强制函数最大代码行数 50// 'max-lines-per-function': ['warn', { max: 70 }],// 强制函数块最多允许的的语句数量20'max-statements': ['warn', 100],// 强制回调函数最大嵌套深度'max-nested-callbacks': ['warn', 3],// 强制函数定义中最多允许的参数数量'max-params': ['warn', 3],// 强制每一行中所允许的最大语句数量'max-statements-per-line': ['warn', { max: 1 }],// 要求方法链中每个调用都有一个换行符'newline-per-chained-call': ['warn', { ignoreChainWithDepth: 3 }],// 禁止 if 作为唯一的语句出现在 else 语句中'no-lonely-if': 'warn',// 禁止空格和 tab 的混合缩进'no-mixed-spaces-and-tabs': 'warn',// 禁止出现多行空行'no-multiple-empty-lines': 'warn',// 禁止出现;semi: ['warn', 'never'],// 强制在块之前使用一致的空格'space-before-blocks': 'warn',// 强制在 function的左括号之前使用一致的空格// 'space-before-function-paren': ['warn', 'never'],// 强制在圆括号内使用一致的空格'space-in-parens': 'warn',// 要求操作符周围有空格'space-infix-ops': 'warn',// 强制在一元操作符前后使用一致的空格'space-unary-ops': 'warn',// 强制在注释中 // 或 /* 使用一致的空格// "spaced-comment": "warn",// 强制在 switch 的冒号左右有空格'switch-colon-spacing': 'warn',// 强制箭头函数的箭头前后使用一致的空格'arrow-spacing': 'warn','prefer-const': 'warn','prefer-rest-params': 'warn','no-useless-escape': 'warn','no-irregular-whitespace': 'warn','no-prototype-builtins': 'warn','no-fallthrough': 'warn','no-extra-boolean-cast': 'warn','no-case-declarations': 'warn','no-async-promise-executor': 'warn',},globals: {defineProps: 'readonly',defineEmits: 'readonly',defineExpose: 'readonly',withDefaults: 'readonly',},}
env 预定义的环境变量
作用:提供预定义的环境变量。
因为node 或者浏览器中的全局变量很多,如果我们一个个声明会显得繁琐,因此就需要用到env,这是对环境定义的一组全局变量的预设。
env: {browser: true,es2021: true, // 添加所有 ECMAScript 2021 全局变量并自动将 ecmaVersion 解析器选项设置为 12node: true,},
parser 指定要使用的解析器
作用:指定要使用的解析器。我们指定为vue-eslint-parser即可
parser: 'vue-eslint-parser',
parserOptions 解析器配置
作用:给解析器传入一些其他的配置参数
比如我们之前安装的@typescript-eslint/parser就可以在这里进行配置
parserOptions: {parser: '@typescript-eslint/parser',ecmaVersion: "latest", // 支持的es版本sourceType: 'module', // 代模块类型,默认为script,我们设置为module},
extends 使用预设配置
作用:使用预设的 lint 包
如果要我们自己去设置各个规则未免会显得繁琐,所以可以直接使用业界的最佳实践作为基础规则
extends: ['plugin:vue/vue3-recommended','plugin:@typescript-eslint/recommended'],
plugins 增强 ESlint 功能
作用:增强 ESlint 功能
还记得我们最开始安装的@typescript-eslint/eslint-plugin吗?它就是用来给 eslint 提供一些额外的适用于 ts 语法的规则插件名中的 eslint-plugin- 可以省略:
// eslint-plugin-vue @typescript-eslint/eslint-plugin eslint-plugin-prettier的缩写plugins: ["vue", "@typescript-eslint", "prettier"],
rules 自定义规则
作用:创建自定义规则。
规则定义值:
- off 或 0 - 关闭规则
- warn 或 1 - 开启规则, 使用警告 程序不会退出
- error 或 2 - 开启规则, 使用错误 程序退出
虽然我们通过 extends 引入了行业内最佳实践的一些规则,但是每个团队还是有每个团队自己的开发习惯,所以我们可以通过 rules 添加或者修改 extends 中的规则。
2. 项目下新建 .eslintignore
# eslint 忽略检查 (根据项目需要自行添加)node_modulesdist
prettier 支持
# 安装 prettieryarn add prettier --dev
解决 eslint 和 prettier 冲突
当 ESLint 的规则和 Prettier 的规则相冲突时,就会发现一个尴尬的问题,用其中一种来格式化代码,另一种就会报错。
prettier 官方提供了一款工具 eslint-config-prettier 来解决 ESLint 中的样式规范和 prettier 中样式规范的冲突,以 prettier 的样式规范为准,使 ESLint 中的样式规范自动失效
# 安装插件 eslint-config-prettieryarn add eslint-config-prettier --dev
上面介绍的工具,仅仅只是将部分 ESLint 规则给禁用了,避免 Prettier 格式化之后的代码导致 ESLint 报错而已,如何将两者结合起来使用呢?
prettier 官方提供了一个 ESLint 插件 eslint-plugin-prettier ,这个插件的主要作用就是将 prettier 作为 ESLint 的规则来使用,相当于代码不符合 Prettier 的标准时,会报一个 ESLint 错误,同时也可以通过 eslint —fix 来进行格式化
yarn add eslint-plugin-prettier --dev
项目下新建 .prettierrc.js
配置
prettier格式化规则:
module.exports = {printWidth: 100, // 超过最大值换行tabWidth: 2, // 缩进字节数useTabs: false, // 缩进不使用tab,使用空格semi: false, // 末尾不加尾号singleQuote: true, // 默认单引号quoteProps: 'as-needed', // 仅在需要时在对象属性添加引号jsxSingleQuote: false, // 在jsx中使用单引号代替双引号trailingComma: 'none', // es5对象属性最后加逗号。none不加bracketSpacing: true, // 在对象,数组括号与文字之间加空格jsxBracketSameLine: false, // 在jsx中把'>' 是否单独放一行arrowParens: 'always', // 箭头函数参数只有一个时是否要有小括号htmlWhitespaceSensitivity: 'ignore', // HTML空白灵敏度,空格被认为是不敏感的vueIndentScriptAndStyle: false, // script、style标签不缩进endOfLine: 'auto',// 覆写默认配置,为某些特定文件制定特定配置overrides: [{files: '*.json',options: {printWidth: 200}}]}
package.json 配置命令
{"script": {"lint": "eslint src --fix --ext .ts,.tsx,.vue,.js,.jsx","prettier": "prettier --write ."}}
上面配置完成后, 可以运行以下命令测试下代码检查个格式化效果:
# eslint 检查yarn lint# prettier 自动格式化yarn prettier
配置 husky + lint-staged
使用
husky+lint-staged助力团队编码规范, husky&lint-staged 安装推荐使用mrm, 它将根据package.json依赖项中的代码质量工具来安装和配置 husky 和 lint-staged,因此请确保在此之前安装并配置所有代码质量工具,如Prettier 和 ESlint
配置 css 预处理器 less
虽然
vite原生支持less/sass/scss/stylus,但是你必须手动安装他们的预处理器依赖
安装
yarn add -D lessyarn add --dev less-loader
配置全局 less 样式文件
在 src/ 下新增 styles 文件夹,用于存放全局样式文件
新建 main.less, 设置一个颜色变量 :
@primary-color: #1890ff;
如何将这个全局样式文件全局注入到项目中呢?配置 Vite 即可:
css: {preprocessorOptions: {less: {additionalData: '@import "@/styles/main.less";', // 没有 resolve.alias 别名的话 路径为./src/styles/main.less},},},
组件中使用
<style scoped lang="less">a {color: @primary-color;}</style>
stylelint 规范 css 的书写风格
安装
- stylelint — 运行工具,
- stylelint-config-standard — stylelint的推荐配置
- stylelint-order — 排序插件(先写定位,再写盒模型,再写内容区样式,最后写 CSS3 相关属性)
- stylelint-config-prettier 关闭所有不必要的或可能与Prettier冲突的规则
yarn add stylelint --devyarn add stylelint-config-prettier stylelint-config-recommended stylelint-config-standard stylelint-config-html --dev
官方提供了stylelint-config-recommended和stylelint-config-standard两种css标准:
stylelint-config-recommended包含可能报错的rule,code format的css标准
stylelint-config-standard继承于recommend,一些常见的css书写标准

Stylelint 14+ 不再包含 Scss,Sass,Less 或者 SugarSS 等预编译器的解析了,所以我们可以通过 extends 引入公共规则
"extends": ["stylelint-config-standard", 'stylelint-config-prettier'],
为了让 stylelint 能够读 vue (.html, .xml, .svelte, .vue 等)文件,我们还需要安装postcss-html
yarn add postcss-html --dev
"customSyntax": "postcss-html"
stylelint-order 是CSS属性排序插件,并且每个规则都支持自动修复(stylelint —fix)
yarn add stylelint-order --dev
package.json 配置命令
"stylelint": "npx stylelint --aei .vue src","stylint:fix": "npx stylelint ./src/**/*.vue --fix"
项目下新建 stylelint.config.js
项目下新建 .stylelintignore
.stylelintignore 用来配置不需要通过 stylelint 约束的文件
# 其他类型文件*.js*.ts*.jpg*.woff# 测试和打包目录/dist/*/public/*public/*/node_modules/
路由 vue-router@4
# 安装路由yarn add vue-router@4
在 src 文件下新增 router 文件夹 => index.ts 文件, 内容如下:
import { createRouter, createWebHistory } from 'vue-router'import type { RouteRecordRaw } from 'vue-router'const basicRouters: RouteRecordRaw[] = [{path: '/',name: 'Root',redirect: '/login'},{path: '/login',name: 'Login',component: () => import('@/views/login/Index.vue'),}]const router = createRouter({history: createWebHistory(),routes: basicRouters,})export default router
修改入口文件 mian.ts :
import { createApp } from 'vue'import App from './App.vue'import router from './router/index'const app = createApp(App)app.use(router)app.mount('#app')
vue-router4.x 支持 typescript,配置路由的类型是 RouteRecordRaw,这里 meta 可以让我们有更多的发挥空间,这里提供一些参考:
title:string; 页面标题,通常必选。icon?:string; 图标,一般配合菜单使用。auth?:boolean; 是否需要登录权限。ignoreAuth?:boolean; 是否忽略权限。roles?:RoleEnum[]; 可以访问的角色keepAlive?:boolean; 是否开启页面缓存hideMenu?:boolean; 有些路由我们并不想在菜单中显示,比如某些编辑页面。order?:number; 菜单排序。frameUrl?:string; 嵌套外链。
这里只提供一些思路,每个项目涉及到的业务都会存在些差异,这里就不作详细讲解了,根据自己业务需求做配置即可。
axios 统一请求封装
# 安装 axiosyarn add axios# 安装 nprogress 用于请求 loading# 也可以根据项目需求自定义其它 loadingyarn add nprogress# 类型声明,或者添加一个包含 `declare module 'nprogress'yarn add @types/nprogress --dev
实际使用中可以根据项目修改,比如RESTful api中可以自行添加put和delete请求,ResType也可以根据后端的通用返回值动态的去修改
新增 service 文件夹,service 下新增 http.ts 文件以及 api 文件夹:

http.ts : 用于axios封装
import axios, { AxiosRequestConfig } from 'axios'import NProgress from 'nprogress'// 设置请求头和请求路径axios.defaults.baseURL = '/api'axios.defaults.timeout = 10000axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'axios.interceptors.request.use((config): AxiosRequestConfig<any> => {const token = window.sessionStorage.getItem('token')if (token) {//@ts-ignoreconfig.headers.token = token}return config},(error) => {return error})// 响应拦截axios.interceptors.response.use((res) => {if (res.data.code === 111) {sessionStorage.setItem('token', '')// token过期操作}return res})interface ResType<T> {code: numberdata?: Tmsg: stringerr?: string}interface Http {get<T>(url: string, params?: unknown): Promise<ResType<T>>post<T>(url: string, params?: unknown): Promise<ResType<T>>upload<T>(url: string, params: unknown): Promise<ResType<T>>download(url: string): void}const http: Http = {get(url, params) {return new Promise((resolve, reject) => {NProgress.start()axios.get(url, { params }).then((res) => {NProgress.done()resolve(res.data)}).catch((err) => {NProgress.done()reject(err.data)})})},post(url, params) {return new Promise((resolve, reject) => {NProgress.start()axios.post(url, JSON.stringify(params)).then((res) => {NProgress.done()resolve(res.data)}).catch((err) => {NProgress.done()reject(err.data)})})},upload(url, file) {return new Promise((resolve, reject) => {NProgress.start()axios.post(url, file, {headers: { 'Content-Type': 'multipart/form-data' },}).then((res) => {NProgress.done()resolve(res.data)}).catch((err) => {NProgress.done()reject(err.data)})})},download(url) {const iframe = document.createElement('iframe')iframe.style.display = 'none'iframe.src = urliframe.onload = function () {document.body.removeChild(iframe)}document.body.appendChild(iframe)},}export default http
除了自己手动封装 axios , 这里还推荐一个 vue3 的请求库: VueRequest, 非常好用, 下面来看看 VueRequest有哪些比较好用的功能吧!!!
- 🚀 所有数据都具有响应式
- 🔄 轮询请求
- 🤖 自动处理错误重试
- 🗄 内置请求缓存
- 💧 节流请求与防抖请求
- 🎯 聚焦页面时自动重新请求
- ⚙️ 强大的分页扩展以及加载更多扩展
- 📠 完全使用 Typescript 编写,具有强大的类型提示
- ⚡️ 兼容 Vite
- 🍃 轻量化
- 📦 开箱即用
官网链接: https://www.attojs.com/
状态管理 pinia
由于 vuex 4 对 typescript 的支持让人感到难过,所以状态管理弃用了 vuex 而采取了 pinia. pinia 的作者是 Vue 核心团队成员
安装 pinia
Pinia 与 Vuex 的区别:
id是必要的,它将所使用 store 连接到 devtools。- 创建方式:
new Vuex.Store(...)(vuex3),createStore(...)(vuex4)。 - 对比于 vuex3 ,state 现在是一个
函数返回对象。 - 没有
mutations,不用担心,state 的变化依然记录在 devtools 中。
# 安装 yarn add pinia@next
main.ts 中增加
# 引入 import {createPinia} from "pinia" # 创建根存储库并将其传递给应用程序 app.use(createPinia())
在 src 文件夹下新增 store 文件夹, 接在在 store 中新增 main.ts
创建 store, mian.ts :
`import {defineStore} from ‘pinia’
export const useMainStore = defineStore({
id: ‘mian’,
state: () =>({
name: ‘超级管理员’
})
})
`
组建中获取 store :
<br /> <br />
getters 用法介绍
Pinia 中的 getter 与 Vuex 中的 getter 、组件中的计算属性具有相同的功能
store => mian.ts
`import {defineStore} from ‘pinia’
export const useMainStore = defineStore({
id: ‘mian’,
state: () => ({
name: ‘超级管理员’,
}),
// getters
getters: {
nameLength: (state) => state.name.length,
}
})
`
组件中使用:
`
