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接口文件(⭐)

在这里插入图片描述

  1. 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,
  });
}

  1. 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还未学习的同学提出建议哈;这是个方向;
纯手打文章,分享分析自己的编写方式,肯定有不完美之处,勿喷;等待完善在继续更新此文章。
到此结束;

每天学习一丢丢
你会发现你的知识加上尤雨溪的知识堪比尤雨溪,加油哈哈哈哈

在这里插入图片描述

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐