05-vue3+ts中axios的封装

vue3+ts中axios的封装

安装 axios

bash 复制代码
npm install axios

一、axios 的类型解析

Axios 几个常用类型:

  • AxiosInstance: axios 实例类型
  • AxiosRequestConfig: axios 请求配置类型
  • AxiosResponse: axios 响应类型
  • AxiosError: axios 错误类型

1、AxiosRequestConfig

AxiosRequestConfig 是我们使用 axios 发送请求传递参数的类型。当然它也是我们请求拦截器里面的参数类型。

2、AxiosInstance

  • AxiosInstance 是 axios 的实例类型。
  • axios.create(config?: AxiosRequestConfig)创建出来的对象都是AxiosInstance类型!

3、AxiosResponse

  • AxiosResponse 是 axios 响应类型。
  • 我们可以在响应拦截器中获取到响应数据。
ts 复制代码
export interface AxiosResponse<T = any>  {
  // 后端接口数据
  data: T;
  // http状态码
  status: number;
  // 来自服务器响应的 HTTP 状态信息
  statusText: string;
  // 响应头
  headers: any;
  // 请求配置信息
  config: AxiosRequestConfig;
  // 请求
  request?: any;
}

4、AxiosError

AxiosError 是 axios 错误类型。可以在请求或响应拦截器中获取到错误信息。

二、封装axios

本质:axios二次封装,就是使用请求和响应拦截器!

1、步骤

  • 1.创建axios实例: axios.create(config配置对象)
  • 2.axios添加请求拦截器:主要是操作config对象:
js 复制代码
axios.interceptors.request.use((config)=>{return config})
  • 3.响应拦截器
js 复制代码
axios.interceptors.response.use((response)=>{return response})

2、实现代码

  • 基于restful风格,提供了相对应的方法,方便调用!
  • 在src目录下,创建api目录,创建request.ts,代码如下:
ts 复制代码
import axios from "axios";
import type { AxiosInstance, AxiosRequestConfig } from "axios";
import { base_url, TOKEN } from "@/config/com/base";
import toast from "@/config/utils/toast";
import { ElLoading } from "element-plus";
import useLoginStore from "@/store/login_store";
import cache from "@/config/utils/cache";
import router from "@/router";
/**
 * axios二次封装,就是使用请求和响应拦截器
 * --- 创建axios对象: axios.create(config配置对象)
 * --- 给axios添加请求拦截器:主要是操作config对象
 *      axios.interceptors.request.use((config)=>{return config})
 * --- 给axios添加响应拦截器:
 *      request.interceptors.response.use();
 * ---------------------------------------------------------
 * -- 定义一个Request类:两个属性
 *    --- 属性:instance:AxiosInstance类型
 *              axios的实例对象
 *    --- 属性:baseConfig: AxiosRequestConfig类型
 *              基本的配置信息:baseURL,timeout
 *    --- 属性:
 * ---------------------------------------------------------
 *  */

// 定义一个类Request!
class Request {
  //axios.create()返回axios对象
  instance: AxiosInstance;
  loadingInstance: any; // 用于存储ElLoading实例的变量
  //axios.create(config配置对象)需要的config
  baseConfig: AxiosRequestConfig = { baseURL: base_url, timeout: 5000 };
  constructor(config: AxiosRequestConfig) {
    // 还得提供额外的config配置!所以使用了Object.assign()
    this.instance = axios.create(Object.assign(this.baseConfig, config));
    //在构造器初始化时候 添加 请求拦截器: 主要操作config对象
    this.instance.interceptors.request.use(
      (config: any) => {
        // 创建ElLoading实例并显示加载提示,这里可以配置一些加载提示的相关属性,比如文本、背景遮罩等
        this.loadingInstance = ElLoading.service({
          text: "正在加载...",
          fullscreen: true,
          background: "rgba(0, 0, 0, 0.05)",
        });
        //添加token:
        const userStore = useLoginStore();
        let token = userStore.token;
        if (token) {
          config.headers["Authorization"] = `Bearer ${token}`;
        }
        return config;
      },
      (error) => {// 请求错误,这里可以用全局提示框进行提示
        return Promise.reject(error);
      }
    );
    this.instance.interceptors.response.use( // 添加响应拦截器
      (res: any) => {
        // console.log('request.ts --- 响应拦截器:'+res);
        // 关闭ElLoading实例,隐藏加载提示
        if (this.loadingInstance) {
          this.loadingInstance.close();
        }
        return res.data;
      },
      // 失败响应
      (err: any) => {
        // 这里是AxiosError类型,所以一般我们只reject我们需要的响应即可
        // 关闭ElLoading实例,隐藏加载提示
        if (this.loadingInstance) {
          this.loadingInstance.close();
        }
        console.log("拦截器--error=" + JSON.stringify(err.response.data.data));
        let message = "";
        switch (err.response.status) {
          case 400:
            message = "code = 400 :" + JSON.stringify(err.response.data.data);
            break;
          case 401:
            console.log("401---token认证失败---");
            message = err.response.data.data?.detail;
            // 这里可以做清空storage并跳转到登录页的操作,处理只需要清空token即可,
            cache.removeCache(TOKEN);
            router.replace("/login");
            // 强制刷新
            window.location.reload();
            break;
          case 403:
            message = "权限不够,拒绝访问(403)";
            break;
          case 404:
            message = "请求地址无效(404)";
            break;
          case 405:
            message = "请求方法不被允许(405)";
            break;
          case 500:
            message = "服务器错误(500)";
            break;
          default:
            message = `连接出错(${err.response.status})!`;
        }
        // 错误消息可以使用全局弹框展示出来 :比如element plus 可以使用 ElMessage
        // `${message},请检查网络或联系管理员!`
        if (err.response.data.data) {
          // toast.error(message + " : " + JSON.stringify(err.response.data.data));
          toast.error(message);
        } else {
          toast.error(message + " : " + "服务器好像没有开启");
        }
        return Promise.reject(err.response);
      }
    );
  }
  // 封装get请求!
  public get(url: string, params?: any): Promise<any> {
    return this.instance.get(url, { params });
  }
  public get_by_id(url: string, id: Number): Promise<any> {
    return this.instance.get(url + id + "/");
  }
  // 封装post请求!保存操作
  public post(url: string, data: any): Promise<any> {
    return this.instance.post(url, data);
  }
  // 封装put请求!
  public put(url: string, data: any): Promise<any> {
    return this.instance.put(url + data.id + "/", data);
  }
  // 根据id删除的方法(资源地址,资源id)
  public delete_by_id(url: string, id: Number): Promise<any> {
    return this.instance.delete(url + id + "/");
  }
  // 根据pic删除的方法:把参数封装到params配置项中
  public delete_pic(url: string, params?: any): Promise<any> {
    return this.instance.delete(url, { params });
  }
  // 把参数封装到data配置项中
  public delete_selected(url: string, data?: any): Promise<any> {
    return this.instance.delete(url, { data });
  }
}
// 默认导出Request实例!
export default new Request({});

封装中使用到的其它依赖文件:

  • base.ts
csharp 复制代码
import { base_url, TOKEN } from "@/config/com/base";
ts 复制代码
// 配置项目的基本信息的文件
//特别注意。图片路径最后要添加斜杠!不然图片显示失败
export const base_url: string = import.meta.env.VITE_APP_BASE_API;
export const TOKEN = "token";
  • toast.ts : 是对Elment-plus的提示信息的封装(个人选择)
ts 复制代码
import toast from "@/config/utils/toast";
ts 复制代码
// 用于封装一些全局的hook,可以单独导入某些方法使用,也可以统一导入 hook 对象,从 hook 对象中 . 具体的方法
import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
/**
 * 封装一个全局的 message 方法,用于显示消息提示
 * @param message  消息内容
 * @param type 消息类型,默认为 success
 */
export const message = (message: string) => {
  ElMessage({
    message,
    type: "success",
  });
};
/**
 * 封装一个全局的 notification 方法,用于显示通知
 *  @param message 通知内容
 *  @param title   通知标题,默认为 '提示'
 */
export const notify = (message: string) => {
  ElNotification({
    // title,
    message,
    type: "success",
  });
};
export const error = (message: string) => {
  ElNotification({
    message,
    type: "error",
  });
};
/**
 * 封装一个全局的 confirm 方法,用于显示确认对话框
 * @param message 对话框内容
 * @param title 对话框标题,默认为 '提示'
 * @param [options] 对话框选项
 * @return Promise<boolean>
 */
export const confirm = (message: string, title = "提示", options: any = {}) => {
  if (Object.keys(options).length == 0) {
    options = {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    };
  }
  return new Promise((resolve, reject) => {
    ElMessageBox.confirm(message, title, options)
      .then(() => {
        resolve(true);
      })
      .catch(() => {
        reject(false);
      });
  });
};
/**
 * 统一导出一个 hook 方法对象,包含所有 hook 方法
 */
export default {
  message,
  confirm,
  notify,
  error,
};
/**
 * 使用该hooks方式如下:
import hooks from "@/config/utils/index";
hooks.message('操作成功') // 成功弹出
hooks.notification('恭喜你学会了使用全局通知组件', '操作成功', { type: 'success' }) // 成功弹出
hooks.confirm('确认要删除吗?').then((res) => console.log(res)) // 成功弹出
 */
  • login_store.ts : 仅给出示例代码
csharp 复制代码
import useLoginStore from "@/store/login_store";
csharp 复制代码
import { defineStore } from "pinia";
import { TOKEN } from "@/config/com/base";
import cache from "@/config/utils/cache";
import { ref } from "vue";
export const useLoginStore = defineStore("login", () => {
    const token = ref("");
    const login = () => {
        // 实现逻辑
    };
    return {
        token,
        login
    }
});
  • cache.ts : 这是封装的localstorage使用的工具类!
csharp 复制代码
import cache from "@/config/utils/cache";
ts 复制代码
/**
 * 封装localStorage的使用:
 * import cache from "@/config/utils/cache";
 * cache.xxx()即可!
 */
class Cache {
  setCache(key: string, value: any) {
    if (value) {
      localStorage.setItem(key, JSON.stringify(value));
    }
  }
  getCache(key: string) {
    const value = localStorage.getItem(key);
    if (value) {
      return JSON.parse(value);
    }
    return "";
  }
  removeCache(key: string) {
    localStorage.removeItem(key);
  }
  clear() {
    localStorage.clear();
  }
}
export default new Cache();

3、发送请求的示例代码:

以下代码是使用request的格式示例:

  • 发送请求即可复制格式,修改参数即可!
ts 复制代码
import request from "@/api/request";

// 以下 用到的请求地址示例:
//  api_sy.user = "/sy/user/", //操作用户的url
// 表单数据
let form = reactive({
	id:xxxx, //修改时候传递!
    username: "",
    password: "",
    name: "",
    phone: '',
    is_active: true,
    is_staff: true,
    avatar: "",
})

发送get请求:

ts 复制代码
// 发送get请求
request.get(api_sy.user, params).then(resp => {
	console.log(resp.data)
})

发送post请求:

ts 复制代码
// 发送post请求
request.post(api_sy.user, form).then(resp => {
	console.log(resp.data)
})

发送put请求:

ts 复制代码
// 发送put请求
request.put(api_sy.user, form).then(resp => {
	console.log(resp.data)
})

发送delete请求:

ts 复制代码
// 发送delete请求
request.delete_by_id(api_sy.user, id).then(resp => {
	console.log(resp.data)
})
相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax