vue3+ts的axios的二次封装以及请求参数(data、params、formData)的区分

有时候在二次封装axios时常常会遇到使用请求参数的问题,下面就是我很好的区分这些参数的各自作用和使用场景,欢迎点赞评论哦~

首先明白axios 的一些基本配置选项

axios 提供了一个非常灵活的配置选项,允许你自定义请求的各种属性。当你使用 axios 或者一个自定义的 axios 实例(如 axiosInstance)时,你可以通过 requestOptions 对象传递这些配置。以下是一些常见的 requestOptions 属性及其用途:

基本请求配置

  1. url (string): 请求的 URL。
  2. method (string): 请求方法(例如 getpostputdelete 等)。默认为 get
  3. baseURL (string): 用于设置请求的基本 URL。
  4. headers (object): 设置请求头。
  5. params (object): 设置 URL 查询参数。
  6. data (any): 发送到服务器的数据。对于 POSTPUT 和 PATCH 请求,这通常是请求体。
  7. timeout (number): 设置请求超时时间(以毫秒为单位)。
  8. responseType (string): 指定响应类型(例如 arraybufferblobdocumentjsontextstream)。
  9. responseEncoding (string): 指定响应编码(例如 utf8)。
  10. xsrfCookieName (string): 用于 CSRF 保护的 cookie 名称。
  11. xsrfHeaderName (string): 用于 CSRF 保护的 HTTP 头名称。
  12. maxContentLength (number): 定义内容的最大长度(以字节为单位)。
  13. maxBodyLength (number): 定义请求体的最大长度(以字节为单位)。
  14. validateStatus (function): 自定义状态码验证函数。
  15. cancelToken (CancelToken): 用于取消请求的令牌。
  16. onUploadProgress (function): 上传进度事件处理程序。
  17. onDownloadProgress (function): 下载进度事件处理程序。
  18. auth (object): 包含 username 和 password 的对象,用于基本认证。
  19. withCredentials (boolean): 是否发送 cookies。
  20. transformRequest (array | function): 在请求发送前对数据进行转换。
  21. transformResponse (array | function): 在响应数据返回后对数据进行转换。

下面是封装的axios(可以借鉴):

import router from '@/router'
import { useTagsViewStore } from '@/store/modules/tagsView'
import { useUserStore } from '@/store/modules/user'
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
import { ElLoading, ElMessageBox } from 'element-plus'
import { Loading } from 'element-plus/es/components/loading/src/service'

let loading = null
class HttpRequest {
  private readonly baseUrl: string = import.meta.env.VITE_BASE_REQUEST_URL
  private defaultConfig() {
    return {
      baseURL: this.baseUrl,
      timeout: 10000,
      withCredentials: true,
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
      },
    }
  }

  private interceptors(instance: AxiosInstance) {
    // 请求拦截
    instance.interceptors.request.use(
      (config) => {
        // 添加全局的loading..
        loading = ElLoading.service({
          fullscreen: true,
          lock: true,
          text: '正在加载...',
          background: 'rgba(0, 0, 0, 0.7)',
        })
        // 请求头携带token
        const UserStore = useUserStore()
        const token = UserStore.token
        if (token) {
          config.headers.Authorization = 'Bearer ' + token
        }
        // console.log('请求拦截config', config)
        return config
      },
      (error: any) => {
        return Promise.reject(error)
      },
    )
    //响应拦截
    instance.interceptors.response.use(
      (res) => {
        // console.log('响应拦截res', res)
        const UserStore = useUserStore()
        const TagsViewStore = useTagsViewStore()

        if (res.data.code != 200 && res.data.code != 401) {
          loading.close()
          ElMessage.error(res.data.msg)
          return Promise.reject(res.data)
        } else if (res.data.code === 401) {
          loading.close()
          ElMessageBox.alert('登录的信息已过期,请重新登录', '提示', {
            confirmButtonText: '确定',
            callback: async () => {
              await router.go(0)
              await UserStore.logout()
              TagsViewStore.clearVisitedView()
              ElMessage({
                type: 'success',
                message: '退出登录成功!需重新登录。',
              })
            },
          })
          // return Promise.reject(res.data)
        }
        loading.close()
        return res
      },
      (error: any) => {
        loading.close()
        return Promise.reject(error)
      },
    )
  }

  public request(options: AxiosRequestConfig) {
    const axiosInstance = axios.create()
    let requestOptions: any = {}
    if (options['method'].toLowerCase() == 'get') {
      requestOptions = this.defaultConfig()
      requestOptions.headers = {}
      requestOptions = Object.assign(requestOptions, options)
    } else {
      requestOptions = this.defaultConfig()
      for (let conf in options) {
        if (conf == 'params') requestOptions['data'] = options[conf]
        else requestOptions[conf] = options[conf]
      }
    }
    this.interceptors(axiosInstance)
    return axiosInstance(requestOptions)
  }
}
const http = new HttpRequest()
export default http

具体代码解析如下:

params(适用axios的get请求):

在使用 axios 发送 GET 请求时,你可以通过 params 参数来传递查询参数。params 是一个对象,其中的键值对会被转换为 URL 查询字符串。

请求接口:http.request({ url: 'api/merAcct/list', method: 'get', params: {pageIndex: 1,pageSize:2}})

对应上面封装axios的逻辑片段

 public request(options: AxiosRequestConfig) {
    const axiosInstance = axios.create()
    let requestOptions: any = {}
    if (options['method'].toLowerCase() == 'get') {
      requestOptions = this.defaultConfig()
      requestOptions.headers = {}
      requestOptions = Object.assign(requestOptions, options)
    }
else {
      requestOptions = this.defaultConfig()
      for (let conf in options) {
        if (conf == 'params') requestOptions['data'] = options[conf]
        else requestOptions[conf] = options[conf]
      }
    }
    this.interceptors(axiosInstance)
    return axiosInstance(requestOptions)
  }

那么在axiosInstance(requestOptions)的requestOptions选项配置里面实际是下面这样的

因为  请求头requestOptions.headers = {}

{

      baseURL: https://localhost:8080/

      url: 'api/merAcct/list',

      params: {pageIndex: 1,pageSize:2}

      timeout: 10000,

      withCredentials: true,

      headers: {},

实际上url会变成

 https://localhost:8080/api/merAcct/list?pageIndex=1&pageSize=20

这就是你的实际请求接口链接

data(适用axios的post请求):

请求接口:http.request({ url: 'api/merAcct/list', method: 'post', params: {pageIndex: 1,pageSize:2}})

对应上面封装axios的逻辑片段

 public request(options: AxiosRequestConfig) {
    const axiosInstance = axios.create()
    let requestOptions: any = {}
    if (options['method'].toLowerCase() == 'get') {
      requestOptions = this.defaultConfig()
      requestOptions.headers = {}
      requestOptions = Object.assign(requestOptions, options)
    } else {
      requestOptions = this.defaultConfig()
      for (let conf in options) {
        if (conf == 'params') requestOptions['data'] = options[conf]
        else requestOptions[conf] = options[conf]
      }

    }
    this.interceptors(axiosInstance)
    return axiosInstance(requestOptions)
  }

那么在axiosInstance(requestOptions)的requestOptions选项配置里面实际是下面这样的

因为if (conf == 'params') requestOptions['data'] = options[conf]所以把params的数据给到data参数,是JSON数据格式

{

      baseURL: https://localhost:8080/

      url: 'api/merAcct/list',

      data: {pageIndex: 1,pageSize:2}

      timeout: 10000,

      withCredentials: true,

      headers: {

        'Content-Type': 'application/json;charset=utf-8',

      },

实际上url会变成

 https://localhost:8080/api/merAcct/list

formData(适用axios的post请求):

axios 中,requestOptions 对象本身并没有一个名为 formData 的属性。formData 通常是指你使用 FormData 对象来构建请求体数据,并将其作为 data 属性传递给 axios 请求。

http.request({ url: 'api/merAcct/list', method: 'post', params:formData})

通过if (conf == 'params') requestOptions['data'] = options[conf]转化成

{

      baseURL: https://localhost:8080/

      url: 'api/merAcct/list',

      data: {pageIndex: 1,pageSize:2}

      timeout: 10000,

      withCredentials: true,

      headers: {
       'Content-Type': 'multipart/form-data' // 设置适当的 Content-Type
      },

讲解就到这了哦,不懂请留言或者私信我~

### Vue3 中使用 Axios 封装 POST 请求并传递 Body 参数Vue3 应用程序中,可以创建一个通用的方法来封装 `Axios` 的 `POST` 请求,并允许传递任意的 `body` 参数。这不仅提高了代码的可重用性和简洁度,还使得管理 API 调用更加方便。 #### 创建 Axios 实例配置默认设置 为了简化每次调用时重复指定的基础 URL 或者其他公共选项,在项目启动初期通常会初始化一次 Axios 客户端实例: ```javascript // src/api/index.js import axios from &#39;axios&#39;; const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // api base_url timeout: 5000 // request timeout }); export default service; ``` 此部分设置了全局使用的基地址以及超时时长[^3]。 #### 编写 Post 方法支持传入 Data 和 Headers 接下来定义具体的 `postRequest` 函数用来执行带有自定义头部信息和负载体(`body`)的实际 HTTP POST 操作: ```javascript // src/utils/request.js import service from &#39;./api&#39;; async function postRequest(url, payload, config={}) { try { const response = await service.post(url, payload, config); return Promise.resolve(response.data); } catch (err) { return Promise.reject(err.response ? err.response.data : err.message); } } ``` 上述代码片段展示了如何利用异步/等待模式发起请求,并且能够接收额外的配置项比如认证令牌或者其他必要的HTTP头字段[^1]。 #### 使用封装好的方法发送带Body参数的Post请求 最后可以在组件内部轻松地调用之前建立的服务层接口来进行实际的数据交互操作: ```javascript <template> <!-- 组件模板 --> </template> <script setup lang="ts"> import { ref } from "vue"; import { postRequest } from "@/utils/request"; let result = ref(null); function submitForm(formData){ let url = "/submit-form"; let bodyParams = formData; postRequest(url,bodyParams,{ headers:{ &#39;Content-Type&#39;: &#39;application/json&#39; } }).then((res)=>{ console.log(res); result.value=res; }); } </script> ``` 这段脚本演示了怎样在一个表单提交事件处理器里边调用了我们先前构建起来的帮助函数去完成向服务器传送用户输入的信息的任务[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值