0 vite环境变量
- 在浏览器环境里使用环境变量,打印如下变量
console.log('import', import.meta)
#打印内容:
{
"url": "http://localhost:5173/src/components/home.vue",
"hot": {
"data": {}
},
"env": {
"BASE_URL": "/",
"MODE": "development",
"DEV": true,
"PROD": false,
"SSR": false
}
}
console.log('import.url', import.meta.env.BASE_URL)
# /
console.log('import.env.MODE', import.meta.env.MODE)
# development
import.meta.env.MODE: {string} 应用运行的模式。
import.meta.env.BASE_URL: {string} 部署应用时的基本 URL。他由base 配置项决定。
import.meta.env.PROD: {boolean} 应用是否运行在生产环境。
import.meta.env.DEV: {boolean} 应用是否运行在开发环境 (永远与import.meta.env.PROD相反)。
- 在项目根目录下创建.env文件,内容
VITE_BASE_URL=http://192.168.19.14:9000
- 在ts代码中通过,如下方式引用
import.meta.env.VITE_BASE_URL
1 yarn整合element-plus
- yarn安装element-plus
yarn add element-plus
yarn add vite @vitejs/plugin-vue
- 修改main.ts,加入element-plus
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { router } from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
createApp(App).use(router).use(ElementPlus).mount('#app')
- 安装插件
//需要分别安装这两个插件
yarn add @types/node
//使用 vite-plugin-compression 可以 gzip 或 brotli 的方式来压缩资源,这一步需要服务器端的配合,vite 只能帮你打包出 .gz 文件。此插件使用简单,你甚至无需配置参数,引入即可。
//开启 gzip 可以极大的压缩静态资源,对页面加载的速度起到了显著的作用。
yarn add vite-plugin-compression
- 修改vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import viteCompression from "vite-plugin-compression"
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), viteCompression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: "gzip",
ext: ".gz",
})],
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
})
2 yarn导入axios
yarn add axios
#qs 依赖 (对请求传的参数转json字符串处理工具)
yarn add qs
- 在src目录下创建utils/request.ts 文件
//引入 axios
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import { debug } from "console";
import qs from "qs";
// //允许跨域携带cookie信息 改配置与后端保持一致
axios.defaults.withCredentials = true;
// 设置重新请求次数
axios.defaults.retry = 10;
// 设置请求延时
axios.defaults.retryDelay = 5000
// 接口类型和方法
interface BaseType {
baseURL: string;
getConfigParams(): any;
interceptors(instance: AxiosInstance, url: string | number | undefined): any;
request(options: AxiosRequestConfig): any;
}
interface AxiosRequestType {
baseURL?: string;
url?: string | undefined;
data?: any;
params?: any;
method?: string;
headers?: any;
timeout?: number;
value?: any;
cancelToken?: any;
}
// 取消重复请求
const CancelToken = axios.CancelToken;
// 用于存储每个请求的取消函数以及对应标识
let sources: any = [];
// 取消函数
let removeSource = (config: any) => {
for (let item in sources) {
if (sources[item].cancelFunction === config.url + "&" + config.method) {
sources[item].cancel("已取消重复请求,请勿重复请求");
sources.splice(item, 1);
}
}
};
let viteURL = import.meta.env.VITE_BASE_URL;
console.log("当前环境的基础路径为:" + viteURL);
class AxiosHttpRequest implements BaseType {
baseURL: string;
timeout: number;
constructor(baseURL: string, timeout: number) {
this.baseURL = viteURL;
this.timeout = 10000;
}
// 配置参数
getConfigParams() {
const config = {
baseURL: this.baseURL,
timeout: this.timeout,
headers: {
"Content-Type": "application/json;charset=UTF-8",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*"
},
};
return config;
}
// 拦截设置
interceptors(config: AxiosInstance, url: string | number | undefined) {
// debugger;
// 请求拦截
config.interceptors.request.use(
(config: AxiosRequestType) => {
// 断网提示 拦截器不在线提示用户网络有问题
if (!navigator.onLine) {
// messageUtil.warn("您的网络故障,请检查!");
return;
}
// 取消重复请求
removeSource(config);
config.cancelToken = new CancelToken((c) => {
// 将取消函数存起来
sources.push({
cancelFunction: config.url + "&" + config.method,
cancel: c,
});
});
// 添加全局的loading..
// loadingUtil.show();
//全局参数统一处理
if (config.method === "post") {
config.data = { ...config.data };
} else {
config.params = { ...config.params };
}
// 请求头携带token
// get请求映射params参数
if (config.method === "get" && config.params) {
let url = config.url + "?";
for (const propName of Object.keys(config.params)) {
const value = config.params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof value !== "undefined") {
if (typeof value === "object") {
for (const key of Object.keys(value)) {
let params = propName + "[" + key + "]";
var subPart = encodeURIComponent(params) + "=";
url += subPart + encodeURIComponent(value[key]) + "&";
}
} else {
url += part + encodeURIComponent(value) + "&";
}
}
}
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
//2.获取时间戳,精确到秒
let getTimestamp = Date.now().toString().substring(0, 10);
let url = config.url;
if (url) {
let indexOf = url.indexOf("?");
if (indexOf > -1) {
config.url = config.url + "×tamp=" + getTimestamp;
} else {
config.url = config.url + "?timestamp=" + getTimestamp;
}
}
if (config.headers) {
// config.headers["Content-Type"] = "application/json;charset=UTF-8";
// config.headers["Access-Control-Allow-Credentials"] = true;
// config.headers["Access-Control-Allow-Origin"] = "*";
// config.headers["Access-Control-Allow-Methods"] = "*";
// console.log("获取pinia中的token:" + userStore().getToken);
// //3.添加请求头token
// if (userStore().token && userStore().getToken != "") {
// config.headers["Authentication"] = userStore().getToken;
// } else {
// //token 不存在跳转到登录页
// router.replace("/login");
// }
}
return config;
},
(error: any) => {
return Promise.reject(error);
}
);
// 响应拦截
config.interceptors.response.use(
(res: any) => {
// debugger;
// 取消重复请求
removeSource(res.config);
// 获取错误信息
if (res.data.body) {
let errCode = res.data.body.errCode;
switch (errCode) {
//token失效重新获取token
case "A0225":
http
.get({
url: viteURL + "/token/refreshToken",
})
.then((res: any) => {
// localStorageUtil.set("accessToken", res.data);
//重新发送请求 TODO
var config = res.config;
return axios(config);
});
break;
case "A0313":
// messageUtil.error("权限不足,请联系管理员");
return Promise.reject(res);
}
} else {
return Promise.resolve(res);
}
},
(error: any) => {
console.error(`axios请求异常:${error}`)
// debugger;
let msg: string;
if (error.response) {
let code: number = error.response.status;
switch (code) {
case 400:
msg = "错误请求";
break;
case 401:
msg = "认证信息已失效";
// router.push("/login");
break;
case 403:
msg = "客户端非法请求";
break;
case 404:
msg = "访问资源不存在";
break;
case 405:
msg = "请求方式错误";
break;
case 500:
msg = "服务器内部异常";
break;
case 503:
msg = "服务不可用";
break;
case 504:
msg = "网络超时";
break;
case 505:
msg = "http版本不支持该请求";
break;
default:
msg = "未知错误,请联系管理员";
break;
}
} else {
msg = error.message;
if (msg == "Network Error") {
msg = "后端接口连接异常";
} else if (msg.includes("timeout")) {
msg = "系统接口请求超时";
} else if (msg.includes("Request failed with status code")) {
msg = "系统接口" + msg.substring(msg.length - 3) + "异常";
}
}
return Promise.reject(error);
}
);
}
/**
* 外部调用方法
* @param options axios请求参数
* @returns 实例
*/
request(options: AxiosRequestConfig) {
const instance = axios.create();
options = Object.assign(this.getConfigParams(), options);
this.interceptors(instance, options.url);
return instance(options);
}
get<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "GET" });
}
post<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "POST" });
}
put<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "PUT" });
}
delete<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "DELETE" });
}
patch<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "PATCH" });
}
}
// 实例化请求类
const http = new AxiosHttpRequest(viteURL, 3000);
export default http;
- 创建src/api/index.ts
import http from "../utils/request";
export function login(data: any) {
return http.post({
url: "/user-root/users/login",
data,
});
}
export function oks() {
return http.get({
url: "/user-root/users/oks"
});
}
3 创建路由及自定义视图
- 文件src/router/index.ts
<template>
<el-container>
<el-form :model="form" label-width="120px">
<el-form-item label="Activity name">
<el-input v-model="form.userName" />
</el-form-item>
<el-form-item label="Activity zone">
<el-input v-model="form.passWord" type="password" placeholder="Please input password" show-password />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">Login</el-button>
<el-button>Cancel</el-button>
</el-form-item>
</el-form>
</el-container>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { login, oks } from '../api/index'
// do not use same name with ref
const form = reactive({
userName: '',
passWord: ''
})
const onSubmit = () => {
// 登录事件
//调用登录请求
login(form).then((response: any): void => {
// 写逻辑的地方 · · ·
console.log('登录请求:', response);
});
// oks().then((response: any): void => {
// console.log('测试get方法:', response);
// });
}
</script>