axios 封装基础请求库

本文介绍了一个基于Vue.js和Axios的HTTP请求库的封装实践,包括配置不同基础请求地址、接口请求loading管理、token处理、参数过滤与trim、错误提示及统一封装post、get请求等。通过设置拦截器实现了请求和响应的处理,如自动显示加载、错误提示和接口错误处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

axios  封装基础请求库,简化接口请求代码。提供以下功能

1、配置不同基础请求地址

2、接口请求loading

3、附带token

4、处理token过期

5、自动过滤参数中null、undefined、''、[]参数

6、自动trim一些字符串参数

7、接口错误自动提示

8、统一post、get请求参数传递,不同像axios那样去区分params、data

import axios from 'axios';
import { ElMessage, ElLoading } from 'element-plus';
import { useRouter } from 'vue-router';
import appConfig from '../config';

const router = useRouter();
// 通过识别路由前缀分别代理到不同的服务器
axios.defaults.headers['content-type'] = 'application/json';
axios.defaults.timeout = 50000;
export default class Request {
  loading // loading 实例

  instance // axios 实例

  constructor(cfg = {}) {
    const baseUrl = cfg.baseUrl || 'apiGateway';
    this.instance = axios.create({
      baseURL: appConfig.gateway[baseUrl],
    });
    this.setInterceptors();
  }

  /**
   * get 请求
   * @param {string} url 请求地址
   * @param {json} param 参数
   * @param {json} config 配置,同post
   * @returns promise
   */
  get(url, param = {}, config) {
    return this.instance.request({
      method: 'post',
      url,
      params: param,
      config,
    });
  }

  /**
   * post 请求
   * @param {string} url 请求地址
   * @param {json} param 参数,网关要求,空参数也要{}
   * @param {json} config 配置
   *  {
   *    showLoading: true,  // 是否显示loading,默认为true
   *    autoShowError: true // 非200的是否自动显示错误,默认为true
   *    autoFilterParam:true // 自动过滤掉参数中的值为null的参数,默认为true
   *    autoTrim: true // 默认过滤字符串参数中两边空格,默认为true,
   *    needToken : true // 是否需要携带token,默认为true
   *  }
   * @returns promise
   */
  post(url, param = {}, config) {
    return this.instance.request({
      method: 'post',
      url,
      data: param,
      config,
    });
  }

  // 排除无用参数目前只过滤null、undefined、''、[],只过滤一层数据
  static filterParam(params) {
    if (params) {
      const keys = Object.keys(params);
      keys.forEach((key) => {
        const item = params[key];
        if (item === null || item === undefined || item === '' || (item instanceof Array && item.length === 0)) {
          // eslint-disable-next-line no-param-reassign
          delete params[key];
        }
      });
    }
  }

  // 去除字符串参数两边空格
  static autoTrimParam(params) {
    if (params) {
      const keys = Object.keys(params);
      keys.forEach((key) => {
        const item = params[key];
        if (typeof item === 'string') {
          // eslint-disable-next-line no-param-reassign
          params[key] = item.trim();
        }
      });
    }
  }

  // 添加拦截器
  setInterceptors() {
    this.setInterceptorsRequest();
    this.setInterceptorsResponse();
  }

  // 添加请求拦截器
  setInterceptorsRequest() {
    this.instance.interceptors.request.use((config) => {
      const newConfig = { ...config };

      // 赋配置默认值
      if (!newConfig.config) {
        newConfig.config = {
          showLoading: true,
          autoShowError: true,
          autoFilterParam: true,
          autoTrim: true,
          needToken: true,
        };
      } else {
        const {
          showLoading = true,
          autoShowError = true,
          autoFilterParam = true,
          autoTrim = true,
          needToken = true,
        } = newConfig.config;

        newConfig.config = {
          showLoading, autoShowError, autoFilterParam, autoTrim, needToken,
        };
      }

      const consumerConfig = newConfig.config;

      if (consumerConfig.showLoading) {
        this.loading = ElLoading.service({
          lock: true,
          text: '加载中...',
          background: 'rgba(255, 255, 255, 0)',
        });
      }
      const token = sessionStorage.getItem('token');
      if (consumerConfig.needToken && token) {
        newConfig.headers['mall-platform-authorization'] = `Bearer ${token}`;
      }

      if (consumerConfig.autoTrim) {
        Request.autoTrimParam(newConfig.data);
        Request.autoTrimParam(newConfig.params);
      }
      if (consumerConfig.autoFilterParam) {
        Request.filterParam(newConfig.data);
        Request.filterParam(newConfig.params);
      }

      return newConfig;
    }, (error) => {
      if (this.loading) {
        this.loading.close();
      }

      ElMessage.error('客户端请求异常,请稍后重试!');
      return Promise.reject(error);
    });
  }

  // 添加响应拦截器
  setInterceptorsResponse() {
    this.instance.interceptors.response.use((response) => {
      if (response) {
        const res = response.data;
        if (this.loading) {
          this.loading.close();
        }
        if (res && res.code === 401) {
          router.push('/login');
          return;
        }

        if (response.config) {
          const { config } = response.config;
          // 非200提示错误
          if (res && res.code !== 200 && config && config.autoShowError) {
            ElMessage.error(`code:${res.status}:${res.message}`);
          }
        }

        return res;
      }
    }, (error) => {
      if (this.loading) {
        this.loading.close();
      }
      ElMessage.error(error.response.data);
      return Promise.reject(error);
    });
  }
}
<think>好的,我现在需要帮用户解决如何使用Axios封装处理表单数据的请求。首先,我需要回顾一下用户提供的引用内容,看看里面有没有相关的信息。用户引用了三个来源,其中引用[2]提到了如何封装get/post请求,引用[3]则提到了表单请求中的content-type需要设置为multipart/form-data,这对文件上传很重要。 接下来,我应该考虑Axios处理表单数据的一般方法。通常,表单数据有两种形式:application/x-www-form-urlencoded和multipart/form-data。前者用于普通表单数据,后者用于包含文件上传的情况。用户的问题可能涵盖这两种情况,但引用[3]特别提到了文件上传,所以需要重点处理multipart/form-data的情况。 首先,对于普通的表单数据(application/x-www-form-urlencoded),Axios默认可能不是这种格式,需要转换数据。这时候可以使用URLSearchParams对象来序列化数据,或者设置headers中的Content-Type为application/x-www-form-urlencoded,并使用qs来转换数据。不过,用户提供的引用中没有提到qs,可能需要建议安装或者使用内置的URLSearchParams。 然后是处理文件上传的情况,即multipart/form-data。这时候需要用到FormData对象来构建数据,并且正确设置Content-Type。不过,根据引用[3],设置Content-Type为multipart/form-data时,通常浏览器会自动处理,所以可能不需要手动设置,否则可能会出错。这部分需要注意,可能需要提醒用户不要手动设置这个头,或者让Axios自动处理。 接下来,我需要整理步骤。首先封装一个Axios实例,设置基础URL和其他默认配置,如引用[2]中的例子。然后,针对表单请求,可能需要添加请求拦截器,根据数据类型调整配置。例如,当数据是FormData时,自动设置Content-Type为multipart/form-data,或者如果是普通表单数据,设置为application/x-www-form-urlencoded,并转换数据格式。 另外,需要处理可能的错误,比如数据转换是否正确,请求头是否正确设置。在代码示例中,要展示如何创建实例,添加拦截器,处理不同数据类型的请求。同时,要提醒用户在小项目中可能不需要这么复杂的封装,参考引用[1]的建议。 可能的问题点:如何判断请求的数据类型,是否需要根据数据类型动态设置请求头?比如,在拦截器中检查data是否是FormData的实例,如果是,就设置对应的Content-Type,并让浏览器自动处理边界。对于普通表单数据,使用URLSearchParams进行转换,并设置对应的Content-Type。 此外,需要考虑到POST请求和PUT等方法的处理,确保封装的方法可以适用于各种HTTP方法。在示例代码中,可以展示如何发送POST请求,传递FormData或普通表单数据。 最后,生成相关问题,比如如何上传文件,处理不同Content-Type,封装的好处等,参考用户提供的示例中的问题结构。</think>### 使用Axios封装表单请求的步骤 #### 1. 创建Axios实例并配置基础路径 通过`axios.create()`创建实例,设置`baseURL`以统一管理接口地址: ```javascript import axios from 'axios' const request = axios.create({ baseURL: 'http://api.example.com', timeout: 5000 }) ``` #### 2. 封装表单请求方法 根据表单数据类型选择处理方式: - **普通表单数据**(键值对):需设置`Content-Type: application/x-www-form-urlencoded`,使用`URLSearchParams`序列化数据: ```javascript export const postFormData = (data) => { const params = new URLSearchParams() for (const key in data) { params.append(key, data[key]) } return request.post('/submit', params, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }) } ``` - **文件上传表单**:使用`FormData`对象且**无需手动设置Content-Type**[^3],浏览器会自动添加`multipart/form-data`及boundary: ```javascript export const uploadFile = (file, metadata) => { const formData = new FormData() formData.append('file', file) formData.append('info', JSON.stringify(metadata)) return request.post('/upload', formData) } ``` #### 3. 添加请求拦截器(可选) 统一处理表单请求配置: ```javascript request.interceptors.request.use(config => { if (config.data instanceof FormData) { config.headers['Content-Type'] = 'multipart/form-data' } else if (typeof config.data === 'object') { config.data = new URLSearchParams(config.data).toString() config.headers['Content-Type'] = 'application/x-www-form-urlencoded' } return config }) ``` #### 4. 在Vue组件中调用 ```javascript // 提交普通表单 const submitForm = () => { postFormData({ username: 'test', age: 25 }) .then(response => console.log(response)) } // 上传文件 const handleUpload = (file) => { uploadFile(file, { category: 'documents' }) .then(res => alert('上传成功')) } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值