基于vue3+typescript+vite二次封装axios总结(已经在实际项目上线)
该文章api由 UomgAPI平台 提供;技术在进步;我也也要跟上技术的步伐,自己总结了下二次封装axios的经验;支持ts(已经在实际项目上线)通常我们的项目会越做越大,页面也会越来越多,如果页面非常的少,直接用axios也没有什么大的影响,那页面组件多了起来,上百个接口呢,这个时候后端改了接口,多加了一个参数什么的呢?那就只有找到那个页面,进去修改.整个过程很繁琐不易于项目的维护和迭代.这个时
基于vue3+typescript+vite二次封装axios总结
vue3+typescript+vite二次封装axios总结(已经在实际项目上线)
该文章api由 UomgAPI平台 提供;
技术在进步;我也也要跟上技术的步伐,自己总结了下二次封装axios的经验;支持ts(已经在实际项目上线)
为什么要二次封装axios?
通常我们的项目会越做越大,页面也会越来越多,如果页面非常的少,直接用axios也没有什么大的影响,那页面组件多了起来,上百个接口呢,这个时候后端改了接口,多加了一个参数什么的呢?那就只有找到那个页面,进去修改.整个过程很繁琐不易于项目的维护和迭代.
这个时候如果我们统一的区管理接口,需要修改某一个接口的时候直接在api里修改对应的请求是不是很方便呢?
配置vite的环境变量(区分生产环境和开发环境)
根目录创建.env.dev
(开发环境) 和 .env.prod
(生产环境)
项目> .env.dev
项目> .env.prod
其中,文件配置规则如下
#(.env.dev文件配置)测试(开发)环境变量
VITE_ENV = development
# base api
# 基础域名
VITE_BASE_API = https://api.uomg.com
# 服务地址
VITE_SERVE_ADD = /api
#(.env.prod文件配置) 生产环境变量 用来区分域名
VITE_ENV = development
# base api
# 基础域名
VITE_BASE_API = https://api.uomg.com
# 服务地址
VITE_SERVE_ADD = /api
配置package.json文件
项目> pagkage.json
–mode 配置文件后缀名
"scripts": {
"dev": "vite --mode dev",
"test": "vite --mode dev",
"prod": "vite --mode prod",
"build": "vue-tsc --noEmit && vite build --mode prod",
"preview": "vite preview"
},
配置完成后,运行yarn dev 或 yarn test 或 打包时会把自定义的环境变量载入进程序
src目录下创建接收环境变量及公用配置的文件(根目录创建config.ts)
项目>src > config.ts
/** 环境变量 */
const ENV = import.meta.env; // vite是以这种方式获取环境变量
/** 基础域名 `https://api.uomg.com` */
export const BASE_URL = ENV.VITE_BASE_API;
/** 基础服务地址 */
export const URL = BASE_URL + '/api';
/** 超时时间 */
export const TIMEOUT = 6000;
utils文件夹下创建request.ts
项目>src>utils>request.ts
创建封装axois文件👇
import axios, { AxiosRequestConfig } from "axios";
import { BASE_URL, TIMEOUT } from "../config";
/**
* @说明 接口请求返回信息 (按照自己的实际情况分配基础请求格式)
*/
// export interface requestReturnType<T = any> {
// /**
// * @说明 返回code状态码
// */
// code: number;
// /**
// * @说明 返回错误code状态码
// */
// errcode?: number;
// /**
// * @说明 返回信息说明
// */
// msg: string;
// /**
// * @说明 返回总体数据
// */
// data: T;
// /**
// * @说明 返回请求成功是否
// */
// success: boolean | null;
// }
export interface requestReturnType<T = any> {
/**
* @说明 返回code状态码
*/
code: number;
/** 数据内容 */
content: T;
}
/** 创建axios实例 */
const instance = axios.create({
timeout: TIMEOUT, // 超时时间
baseURL: BASE_URL,
headers: {
"Content-Type": "application/json",
},
});
/** 添加请求拦截 */
instance.interceptors.request.use(
(config) => {
console.log("config", config);
// if (config.showLoading) {
// showFullScreenLoading()
// }
/** 请求拦截-可做网络加载开始动作 */
// ...
return config;
},
(err) => {
return Promise.reject(err);
}
);
/** 响应拦截 */
instance.interceptors.response.use(
(response) => {
// if (response.config.showLoading) {
// tryHideFullScreenLoading()
// }
/** 响应拦截-可做网络加载完成动作 */
// ...
return response;
},
(error) => {
// tryHideFullScreenLoading()
console.log(`error:`, error);
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = "错误请求";
break;
case 401:
error.message = "未授权,请重新登录";
break;
case 403:
error.message = "拒绝访问";
break;
case 404:
error.message = "请求错误,未找到该资源";
break;
case 405:
error.message = "请求方法未允许";
break;
case 408:
error.message = "请求超时";
break;
case 500:
error.message = "服务器端出错";
break;
case 501:
error.message = "网络未实现";
break;
case 502:
error.message = "网络错误";
break;
case 503:
error.message = "服务不可用";
break;
case 504:
error.message = "网络超时";
break;
case 505:
error.message = "http版本不支持该请求";
break;
default:
error.message = `连接错误${error.response.status}`;
}
} else {
error.message = "连接到服务器失败";
}
/** 错误逻辑处理,此处可在页面弹框处理 */
// ...
return Promise.reject(error.message);
}
);
/** 代理请求 */
// 注意此处的泛型T,默认值时any;兼容未提供指定类型的方式
async function httpProxy<T = any>(config: AxiosRequestConfig): Promise<requestReturnType<T>> {
let resData = await instance(config);
return resData.data;
}
export default httpProxy;
创建管理api接口文件(⭐)
- requestList.ts
项目>src>api>requestList.ts
requestList.ts
文件来管理多个api的文件;
参考如下:
import httpProxy from "../utils/request"; // 拿到我们刚封装的axios
import { URL } from "../config"; // 根据环境变量拿到的域名服务地址
/** 导入接口返回类型 */
import { qinghuaType } from "./models";
/** 请求接口:情话
** 接口地址:https://api.uomg.com/api/rand.qinghua
** 返回格式:json/html
** 请求方式:get/post
** 请求示例:https://api.uomg.com/api/rand.qinghua?format=json
** 请求参数说明:
** 名称 必填 类型 说明
** format 否 string 选择输出格式[json|text|js]
** 返回参数说明:
**
** 名称 类型 说明
** code string 返回的状态码
** content string 返回文本信息
** msg string 返回错误提示信息!
*
*/
// 参数泛型 <T extends Record<string, any>> 表示,给我的参数类型,必须约束于对象形式 即{key:value,...}模式,key类型string,value类型为any &&&&& 可根据实际情况变更此params类型
export async function getQingHua<T extends Record<string, any>>(params: T | undefined) {
/** @qinghuaType 返回台参数类型 */
return await httpProxy<qinghuaType>({
url: URL + "/rand.qinghua",
method: "GET",
params,
});
}
- model>index.ts
项目>src>api>model>index.ts
model>index.ts
此文件设计为接口返回类型声明文件(后台的每个接口返回的数据类型,我在此处标记一下)
/** @说明 : 后台接口返回 情话类型 */
export type qinghuaType = string; // 说明,情话 -- 这个接口 ,返回的数据类型确定时字符串类型
/** 例如 其他数据返回格式 也可以这样定义 */
export interface testType {
url:string;
data:string[]; // Array<string> 也可
count:number;
// ...
}
此处注意;别混淆哈;在我们定义getQingHua
函数时,传的泛型是指我们参数的格式
开发技巧(彩蛋⭐)
有一个小彩蛋哈,我们再给变量
、函数
、类
、对象的key
写注释时,尽量用/** */
的语法,因为vscode会提供我们提示哈
实际页面使用接口请求(⭐)
项目>src>views>A.vue
在A.vue中使用,例如:
<template>
<div>
{{state.data}}
</div>
</template>
<script setup>
import { reactive } from "vue";
import { getQingHua } from '../api/requestList'
const state = reactive({
data:""
})
state.data = await getQingHua({format:"json"});
console.log(`state:`, state);
</script>
<style lang="scss" scoped>
</style>
此时我们测试一下,用一个变量接收一下数据,看看能不能用.
的语法点出来他的类型数据
可以看到,我们定义的类型数据点出来了;
再看一下我们的数据类型👇
定义的确定是字符串类型,出来了
看到没?鼠标划入content 备注也出来了,这就是/** */
注释语法的强大之处
每个自己写的注释都能出来了
结束
vue3+typescript对开发着非常友好了,比vue2时代强太多了;同时对typescript还未学习的同学提出建议哈;这是个方向;
纯手打文章,分享分析自己的编写方式,肯定有不完美之处,勿喷;等待完善在继续更新此文章。
到此结束;
每天学习一丢丢
你会发现你的知识加上尤雨溪的知识堪比尤雨溪,加油哈哈哈哈
更多推荐
所有评论(0)