> {
readonly VITE_ENV: string; // 环境
readonly VITE_OUTPUT_DIR: string; // 打包目录
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
```
## ✅ 配置 alias 别名
- 文档:https://cn.vitejs.dev/config/#resolve-alias
- 修改 vite.config.ts 配置
```js
resolve: {
alias: {
"@": "/src",
},
},
```
## ✅ Sass 全局样式
- 文档:https://cn.vitejs.dev/guide/features.html#css-pre-processors
1. 安装依赖
使用`dart-sass`, 安装速度比较快,大概率不会出现安装不成功
```js
npm i -D sass
```
2. 使用
每个页面自己对应的样式都写在自己的 .vue 文件之中 `scoped` 它顾名思义给 css 加了一个域的概念。
```html
```
### vite 识别 sass 全局变量
- 文档:https://cn.vitejs.dev/config/#css-preprocessoroptions
* vite.config.js 添加配置
```js
css: {
preprocessorOptions: {
scss: {
additionalData: `
@import "@/styles/mixin.scss";
@import "@/styles/variables.scss";
`,
},
},
},
```
## ✅ 识别 nodejs 内置模块
- path 模块是 node.js 内置的功能,但是 node.js 本身并不支持 typescript,所以直接在 typescript 项目里使用是不行的
- 解决方法:安装@types/node
```js
npn i -D @types/node
```
- 在 vite.config.js 中使用
```js
import { resolve } from 'path'
```
## ✅ Vue-router自动生成路由
- 文档:https://next.router.vuejs.org/zh/installation.html
### 1. 安装依赖
```ts
npm install vue-router
npm install vite-plugin-pages -D
```
### 2. 配置自动生成路由
- 在 src 目录下,新建 router 文件夹,并在文件夹内创建
- index.ts 配置自动生成路由
```ts
import { createRouter, createWebHistory } from 'vue-router';
import routes from 'pages-generated';
const router = createRouter({
history: createWebHistory(), // HashHistory
routes,
});
export default router;
```
+ vite.config.js 添加配置,自动根据src/views下的文件生成路由
```ts
export default defineConfig({
plugins: [
Pages({
pagesDir: [
{
dir: 'src/views',
baseRoute: '',
},
],
exclude: ['**/components/*.vue'],
}),
]
});
```
### 3. mian 中引入 router
```ts
import { createApp } from 'vue'
import router from './router'
import App from './App.vue'
// 引入全局样式
import '@/styles/index.scss'
const app = createApp(App)
app.use(router)
app.mount('#app')
```
### 4. app.vue 和 layout 配置 router-view
```ts
// app.vue
```
## ✅ Pinia 状态管理
- 文档:https://pinia.vuejs.org/
- 参考资料:https://juejin.cn/post/7049196967770980389
- Pinia 的特点:
- 完整的 typescript 的支持;
- 足够轻量,压缩后的体积只有 1.6kb;
- 去除 mutations,只有 state,getters,actions(这是我最喜欢的一个特点);
- actions 支持同步和异步;
- 没有模块嵌套,只有 store 的概念,store 之间可以自由使用,更好的代码分割;
- 无需手动添加 store,store 一旦创建便会自动添加;
### 安装依赖
```js
npm i pinia
```
### 创建 Store
- 新建 src/store 目录并在其下面创建 index.ts,导出 store
```js
// src/store/index.ts
import { createPinia } from 'pinia'
const store = createPinia()
export default store
```
### 在 main.ts 中引入并使用
```ts
// src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
const app = createApp(App)
app.use(store)
```
### 定义 State
- 在 src/store 下面创建一个 user.ts
```ts
//src/store/user.ts
import { defineStore } from 'pinia'
import { useAppStore } from './app'
export const useUserStore = defineStore({
id: 'user',
state: () => {
return {
name: '张三',
age: 18
}
},
getters: {
fullName: (state) => {
return state.name + '丰'
}
},
actions: {
updateState(data: any) {
this.$state = data
this.updateAppConfig()
},
updateAppConfig() {
const appStore = useAppStore()
appStore.setData('app-update')
}
}
})
```
```ts
//src/store/app.ts
import { defineStore } from 'pinia'
export const useAppStore = defineStore({
id: 'app',
state: () => {
return {
config: 'app'
}
},
actions: {
setData(data: any) {
console.log(data)
this.config = data
}
}
})
```
### 获取/更新 State
```vue
姓名:{{ name }}
年龄:{{ age }}
计算的名字:{{ userStore.fullName }}
app的config: {{ appStore.config }}
```
### 数据持久化
- 文档:https://github.com/prazdevs/pinia-plugin-persistedstate
* 插件 pinia-plugin-persistedstate 可以辅助实现数据持久化功能。
* 数据默认存在 sessionStorage 里,并且会以 store 的 id 作为 key。
* 安装依赖
```ts
npm i pinia-plugin-persistedstate
```
- 引用插件
```ts
// src/store/index.ts
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const store = createPinia()
store.use(piniaPluginPersistedstate)
export default store
```
- 在对应的 store 里开启 persist 即可
```ts
export const useUserStore = defineStore({
id: 'user',
state: () => {
return {
name: '张三'
}
},
// 开启数据缓存
persist: {
key: 'user',
storage: sessionStorage, // 数据存储位置,默认为 localStorage
paths: ['name'], // 用于部分持久化状态的点表示法路径数组,表示不会持久化任何状态(默认为并保留整个状态)
overwrite: true
}
})
```
## ✅ Axios 封装及接口管理
### 安装依赖
```js
npm i axios
```
### 封装Axios
在src/service/下创建request.ts文件来封装axios
```typescript
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
class HttpRequest {
getInsideConfig() {
const config = {
baseURL: import.meta.env.VITE_API_BASE_URL, // 所有的请求地址前缀部分(没有后端请求不用写)
timeout: 80000, // 请求超时时间(毫秒)
withCredentials: true, // 异步请求携带cookie
// headers: {
// 设置后端需要的传参类型
// 'Content-Type': 'application/json',
// 'token': x-auth-token',//一开始就要token
// 'X-Requested-With': 'XMLHttpRequest',
// },
};
return config;
}
// 请求拦截
interceptors(instance: AxiosInstance, url: string | number | undefined) {
instance.interceptors.request.use(
(config) => {
// 添加全局的loading..
// 请求头携带token
return config;
},
(error: any) => {
return Promise.reject(error);
}
);
//响应拦截
instance.interceptors.response.use(
(res) => {
//返回数据
const { data } = res;
console.log('返回数据处理', res);
return data;
},
(error: any) => {
console.log('error==>', error);
return Promise.reject(error);
}
);
}
request(options: AxiosRequestConfig) {
const instance = axios.create();
options = Object.assign(this.getInsideConfig(), options);
this.interceptors(instance, options.url);
return instance(options);
}
}
const http = new HttpRequest();
export default http;
```
### 接口管理
在src/apis/下创建user.ts文件用来管理用户相关的接口
```typescript
import http from '../service/request';
const PREFIX = 'user';
export const getTest = (params: any) => {
return http.request({
url: `${PREFIX}/test`,
method: 'post',
params,
});
};
```
## ✅ 配置 proxy 跨域
在vite.config.ts进行如下配置
```typescript
export default defineConfig({
plugins: [vue()],
// 在文件中添加以下内容
server: {
proxy: {
'/api': {
target: 'http://xxxxxxxxxxxxxxx',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
}
})
```
## ✅ Element Plus 自动按需引入
### 安装依赖
```bash
npm i element-plus
npm i -D @iconify-json/ep unplugin-auto-import unplugin-icons unplugin-vue-components
```
在vite.config.ts进行如下配置
```typescript
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import Icons from 'unplugin-icons/vite';
import IconsResolver from 'unplugin-icons/resolver';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
export default defineConfig({
plugins: [
AutoImport({
resolvers: [
ElementPlusResolver(),
// 自动导入图标组件
IconsResolver({
prefix: 'Icon',
}),
],
dts: path.resolve(__dirname, 'types/auto-imports.d.ts'),
}),
Components({
resolvers: [
ElementPlusResolver(),
// 自动注册图标组件
IconsResolver({
enabledCollections: ['ep'],
}),
],
dts: path.resolve(__dirname, 'types/components.d.ts'),
}),
Icons({
autoInstall: true,
}),
],
})
```
## ✅ Markdown预览
### 安装依赖
```bash
npm i highlight.js
npm i -D vite-plugin-md
```
在vite.config.ts进行如下配置
```typescript
import Markdown from 'vite-plugin-md';
import hljs from 'highlight.js';
export default defineConfig({
plugins: [
Markdown({
markdownItOptions: {
html: true,
linkify: true,
typographer: true,
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return (
'' +
hljs.highlight(str, { language: lang, ignoreIllegals: true })
.value +
'
'
);
} catch (__) {}
}
return '';
},
},
}),
],
})
```
在vue组件中使用
```vue
```
## ✅ Eslint + Prettier 统一开发规范
### 1. 安装依赖
```js
npm i -D eslint eslint-plugin-vue prettier @vue/eslint-config-prettier @vue/eslint-config-typescript @rushstack/eslint-patch
```
### 2. 编写相关文件
- .eslintrc.js
```js
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript/recommended',
'@vue/eslint-config-prettier'
],
env: {
'vue/setup-compiler-macros': true
},
parserOptions: {
ecmaVersion: 12
},
rules: {
'prettier/prettier': 'warn',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off'
}
}
```
- .prettierc.js
```js
module.exports = {
// 定制格式化要求
overrides: [
{
files: '.prettierrc',
options: {
parser: 'json'
}
}
],
printWidth: 100, // 一行最多 100 字符
tabWidth: 2, // 使用 4 个空格缩进
semi: false, // 行尾需要有分号
singleQuote: true, // 使用单引号而不是双引号
useTabs: false, // 用制表符而不是空格缩进行
quoteProps: 'as-needed', // 仅在需要时在对象属性两边添加引号
jsxSingleQuote: false, // 在 JSX 中使用单引号而不是双引号
trailingComma: 'none', // 末尾不需要逗号
bracketSpacing: true, // 大括号内的首尾需要空格
bracketSameLine: false, // 将多行 HTML(HTML、JSX、Vue、Angular)元素反尖括号需要换行
arrowParens: 'always', // 箭头函数,只有一个参数的时候,也需要括号 avoid
rangeStart: 0, // 每个文件格式化的范围是开头-结束
rangeEnd: Infinity, // 每个文件格式化的范围是文件的全部内容
requirePragma: false, // 不需要写文件开头的 @prettier
insertPragma: false, // 不需要自动在文件开头插入 @prettier
proseWrap: 'preserve', // 使用默认的折行标准 always
htmlWhitespaceSensitivity: 'css', // 根据显示样式决定 html 要不要折行
vueIndentScriptAndStyle: false, //(默认值)对于 .vue 文件,不缩进