一、 集成Element-plus
该项目使用的框架是element-plus,首先需要安装和配置element-plus。
1.安装Element Plus和图标组件
npm install element-plus @element-plus/icons-vue
2.全局注册
main.ts:
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
createApp(App).use(ElementPlus).mount('#app)
3.Element Plus全局组件类型声明
// tsconfig.json
{
"compilerOptions": {
// ...
"types": ["element-plus/global"]
}
}
4. 页面使用 Element Plus 组件和图标
<!-- src/App.vue -->
<template>
<div style="text-align: center;margin-top: 10px">
<el-button :icon="Search" circle></el-button>
<el-button type="primary" :icon="Edit" circle></el-button>
<el-button type="success" :icon="Check" circle></el-button>
<el-button type="info" :icon="Message" circle></el-button>
<el-button type="warning" :icon="Star" circle></el-button>
<el-button type="danger" :icon="Delete" circle></el-button>
</div>
</template>
<script lang="ts" setup>
import HelloWorld from '/src/components/HelloWorld.vue'
import {Search, Edit,Check,Message,Star, Delete} from '@element-plus/icons-vue'
</script>
二、路径别名配置
1.vite.config.ts配置
// vite.config.ts
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src
}
}
})
引用path的时候会报类型错误,记得npm add -D @types/node,安装完以后会多一个文件tsconfig.node.json。
2.TypeScript 编译配置
因为 typescript 特殊的 import 方式 , 需要配置允许默认导入的方式,还有路径别名的配置。
// tsconfig.json
{
"compilerOptions": {
"baseUrl": "./", // 解析非相对模块的基地址,默认是当前目录
"paths": { //路径映射,相对于baseUrl
"@/*": ["src/*"]
},
"allowSyntheticDefaultImports": true // 允许默认导入
}
}
三、环境变量配置
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '商城后台管理系统'
VITE_APP_PORT = 3002
VITE_APP_BASE_API = '/dev-api'
配置运行命令:
"scripts": {
"dev": "vite", // dev环境不需要添加 --mode,默认就是 development
"build:test": "vue-tsc && vite build --mode test",
"build:pro": "vue-tsc && vite build --mode production",
}
可以通过process.env.NODE_ENV获取环境变量。获取其他的变量:可通过loadEnv()函数可以获取配置文件中的参数。
import { defineConfig, loadEnv } from 'vite'
export default defineConfig((config) => {
// 根据当前工作目录中的 `mode` 加载 .env 文件
// 设置第三个参数为 '' 来加载所有环境变量,而不管是否有 `VITE_` 前缀。
const { command, mode } = config
const env = loadEnv(mode, process.cwd(), '')
console.log(env.VITE_APP_TITLE)
})
四、集成Axios
Axios 是一个流行的基于 Promise 的 HTTP 客户端库,用于在浏览器和 Node.js 中发出 HTTP 请求。Axios 还支持请求和响应的拦截器。
1.请求拦截
请求拦截会在请求发送之前执行,一般用于:
- 修改请求配置(请求头添加token等);
- 在请求发送前展示加载动画或提示用户 请求拦截器使用 axios.interceptors.request.use() 方法来注册。该方法接受两个函数作为参数,第一个函数用于成功拦截请求,第二个函数用于拦截请求发生错误的情况。
2.响应拦截
响应拦截会在接收到响应数据后执行,一般用于:
- 根据错误状态码进行全局提示处理
- 对响应数据进行格式化或转换并返回
- 在接收到响应后隐藏加载动画或处理其他通用逻辑 和请求拦截一样,该方法也接受两个函数作为参数。
完整代码(utils/http/index.ts)
import axios from "axios";
import { useUserStore } from "@/store/modules/user";
import router from "@/router/index";
import type {
AxiosInstance,
AxiosError,
AxiosRequestConfig,
AxiosResponse,
} from "axios";
import type { ResultsData } from "./type";
import { ElMessage } from "element-plus";
import resetStore from "../reset";
const instance: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 1000,
});
// 添加请求拦截器
instance.interceptors.request.use(
(config) => {
const userStore = useUserStore();
// 在发送请求之前做些什么
const token = userStore.token;
if (token) {
config.headers.token = token;
}
return config;
},
(error: AxiosError) => {
// 对请求错误做些什么
ElMessage.error(error);
return Promise.reject(error);
},
);
// 添加响应拦截器
instance.interceptors.response.use(
(response: AxiosResponse) => {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
const { data } = response;
// 登录失效
if (data?.code === 203) {
ElMessage.error(data.message || "请求失败");
resetStore();
router.replace("/login");
return Promise.reject(data);
}
if (data?.code !== 200) {
ElMessage.error(data.message || "请求失败");
return Promise.reject(data);
}
return data;
},
(error: AxiosError) => {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
let message = "";
// HTTP 状态码
const status = error.response?.status;
switch (status) {
case 401:
message = "token 失效,请重新登录";
break;
case 403:
message = "拒绝访问";
break;
case 404:
message = "请求地址错误";
break;
case 500:
message = "服务器故障";
break;
default:
message = "网络连接故障";
}
ElMessage.error(message);
return Promise.reject(error);
},
);
const http = {
get<T>(
url: string,
data?: object,
config?: AxiosRequestConfig,
): Promise<ResultsData<T>> {
return instance.get(url, { data, ...config });
},
post<T>(
url: string,
data?: object,
config?: AxiosRequestConfig,
): Promise<ResultsData<T>> {
return instance.post(url, data, config);
},
put<T>(
url: string,
data?: object,
config?: AxiosRequestConfig,
): Promise<ResultsData<T>> {
return instance.put(url, data, config);
},
delete<T>(
url: string,
data?: object,
config?: AxiosRequestConfig,
): Promise<ResultsData<T>> {
return instance.delete(url, { data, ...config });
},
};
export default http;
五、集成Pinia
yarn add pinia
# 或者使用 npm
npm install pinia
1.创建一个 pinia
新建store/index.ts
import { createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
const pinia = createPinia();
// piniaPersist(持久化)
pinia.use(piniaPluginPersistedstate);
export default pinia;
在main.ts使用pinia
import { createApp } from 'vue'
import pinia from "@/store";
createApp(App).use(pinia).mount('#app')
2.定义一个store
defineStore的第一个参数是store唯一的id,注意不能重复。
新建modules/user/index.ts:
import { defineStore } from "pinia";
import type { UserInfo } from "./type";
import { getUserInfo, logout } from "@/api";
import { useAuthStore } from "../auth";
import RESEETSTORE from "@/utils/reset";
//一个参数是应用程序中 store 的唯一 id
export const useUserStore = defineStore("user", {
state: () => {
return {
userInfo: null,
token: "",
};
},
actions: {
setUserInfo(userInfo: UserInfo) {
this.userInfo = userInfo;
},
setToken(token: string) {
this.token = token;
},
async GetInfoAction() {
const authStore = useAuthStore();
const { data } = await getUserInfo();
const { avatar, name, buttons, roles, routes } = data;
this.setUserInfo({ avatar, name });
authStore.setAuth({ buttons, roles, routes });
},
async logout() {
await logout();
RESEETSTORE();
},
},
//持久化配置
persist: true,
});
3.使用useUserStore
通过const userStore = useUserStore(),获取到对应store的所有信息,包活state、action、gettter等。
在login.vue中使用:
import { useUserStore } from "@/store/modules/user";
const userStore = useUserStore();
const handleSubmitForm = (formEle: FormInstance | undefined | null) => {
formEle.validate(async (valid) => {
if (valid) {
let { data } = await login(loginForm);
userStore.setToken(data);
}
});
};
六、集成router
安装vue-router
npm install vue-router@4
1.创建路由实例
官网例子:
// 1. Define route components.
// These can be imported from other files
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }
// 2. Define some routes
// Each route should map to a component.
// We'll talk about nested routes later.
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
]
// 3. Create the router instance and pass the `routes` option
// You can pass in additional options here, but let's
// keep it simple for now.
const router = VueRouter.createRouter({
// 4. Provide the history implementation to use. We are using the hash history for simplicity here.
history: VueRouter.createWebHashHistory(),
routes, // short for `routes: routes`
})
// 5. Create and mount the root instance.
const app = Vue.createApp({})
// Make sure to _use_ the router instance to make the
// whole app router-aware.
app.use(router)
app.mount('#app')
// Now the app has started!
首先定义route,并引入组件映射
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
export const constantRoutes: Array<RouteRecordRaw> = [
{
path: '/',
component: () => import('@/views/home/index.vue'),
},
{
path: '/login',
component: () => import('@/views/login/index.vue'),
},
{
path: '/401',
component: () => import('@/views/error-page/index.vue'),
},
]
// 创建路由实例
const router = createRouter({
history: createWebHashHistory(),
routes: constantRoutes as RouteRecordRaw[],
// 刷新时,滚动条位置还原
scrollBehavior: () => ({ left: 0, top: 0 }),
})
export default router
main.ts中,全局注册router
// main.ts
import router from "@/router";
const app = createApp(App)
app.use(router).mount('#app')