# ①在 Vue3+Ts 项目中封装 axios

# 说明

采用了类封装思想,包含了三种情况的拦截器封装

①公共拦截器(所有实例都有的拦截器)

②特有拦截器(只有在 new 实例时传入的对象中传入了拦截器)

③独有拦截器(只有在调用请求的时候传入拦截器)

# 实现代码

在用 cli 脚手架创建完成项目后

在 src 下面创建 network 文件夹,在里面创建 index.ts

该文件是拿到 axios 请求封装实例并导出使用(网络请求出口)

// src/network/index.ts
//network 的统一出口
import NWRequest from './request'
// 这里是有传入特有拦截器的实例
const nwRequest = new NWRequest({
  baseURL: process.env.VUE_APP_BASE_URL,
  timeout: process.env.VUE_APP_TIME_OUT,
  interceptors: {
    requestInterceptor: (config) => {
      console.log('在new实例时有传入拦截器的实例才有的拦截器:请求成功的拦截')
      return config
    },
    requestInterceptorCatch: (err) => {
      console.log('在new实例时有传入拦截器的实例才有的拦截器:请求失败的拦截')
      return err
    },
    responseInterceptor: (config) => {
      console.log('在new实例时有传入拦截器的实例才有的拦截器:响应成功的拦截')
      return config
    },
    responseInterceptorCatch: (err) => {
      console.log('在new实例时有传入拦截器的实例才有的拦截器:响应失败的拦截')
      return err
    }
  }
})
// 这里是没有有传入特有拦截器的实例
const nwRequest1 = new NWRequest({
  baseURL: process.env.VUE_APP_BASE_URL,
  timeout: process.env.VUE_APP_TIME_OUT
})
export { nwRequest, nwRequest1 }

在 src 的 network 下创建 request 文件夹,在里面创建 type.ts

该文件是为了定义 ts 的限制类型接口 interface

import type { AxiosRequestConfig, AxiosResponse } from 'axios'
interface NWRequestInterceptors<T = AxiosResponse> {
  requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
  requestInterceptorCatch?: (error: any) => any
  responseInterceptor?: (res: T) => T
  responseInterceptorCatch?: (error: any) => any
}
interface NWRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
  interceptors?: NWRequestInterceptors<T>
}
export { NWRequestInterceptors, NWRequestConfig }

在 src 的 network 下的 request 文件夹,在里面创建 index.ts

该文件是 axios 主要封装类

// src/network/request/index.ts
import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { NWRequestInterceptors, NWRequestConfig } from './type'
// 定义网络请求的封装类
class NWRequest {
  instance: AxiosInstance
  interceptors?: NWRequestInterceptors
  constructor(config: NWRequestConfig) {
    this.instance = axios.create(config)
    this.interceptors = config.interceptors
    // 从 config 中取出的拦截器是对应的实例的拦截器
    // 只有 new 实例的时候有传入拦截器才有
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )
    // 添加所有的实例都有的拦截器
    this.instance.interceptors.request.use(
      (config) => {
        console.log('所有的实例都有的拦截器:请求成功拦截')
        return config
      },
      (err) => {
        console.log('所有的实例都有的拦截器:请求失败拦截')
        return err
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
        console.log('所有的实例都有的拦截器:响应成功拦截')
        return res
      },
      (err) => {
        console.log('所有的实例都有的拦截器:响应失败拦截')
        return err
      }
    )
  }
  request<T>(config: NWRequestConfig<T>): Promise<T> {
    return new Promise((resolve, reject) => {
      // 这里的作用是,如果在调用请求的时候想添加额外单独的拦截器
      if (config.interceptors?.requestInterceptor) {
        config = config.interceptors.requestInterceptor(config)
      }
      this.instance
        .request<any, T>(config)
        .then((res) => {
          if (config.interceptors?.responseInterceptor) {
            res = config.interceptors.responseInterceptor(res)
          }
          resolve(res)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }
  get<T>(config: NWRequestConfig<T>): Promise<T> {
    return this.request<T>({
      ...config,
      method: 'GET'
    })
  }
  post<T>(config: NWRequestConfig<T>): Promise<T> {
    return this.request<T>({
      ...config,
      method: 'POST'
    })
  }
}
export default NWRequest

# 测试

在 src 下的 main.ts 中

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { nwRequest } from './network'
const app = createApp(App)
app.use(router)
app.use(store)
app.mount('#app')
// 该请求包含公共拦截器、特有拦截器
nwRequest.request({
  url: '/login',
  method: 'POST',
  data: {
    name: '哈哈哈',
    password: '123456'
  }
})
nwRequest
  .post({
    url: '/login',
    data: {
      name: '哈哈哈',
      password: '123456'
    }
  })
  .then((res) => {
    console.log(res)
  })
// 该请求包含公共拦截器、独有拦截器
// nwRequest1.request({
//   url: '/login',
//   method: 'POST',
//   data: {
//     name: ' 哈哈哈 ',
//     password: '123456'
//   },
//   interceptors: {
//     requestInterceptor: (config) => {
//       console.log (' 独有拦截器:单独请求的 config')
//       return config
//     }
//   }
// })
// 该请求质只包含公共拦截器
// nwRequest1.request({
//   url: '/login',
//   method: 'POST',
//   data: {
//     name: ' 哈哈哈 ',
//     password: '123456'
//   }
// })

# ②删减版

# 说明

该部分在上面完整的基础上删减去一些类型限制,完整版里面甚至连返回的数据类型都做了限制,比较难懂

①公共拦截器(所有实例都有的拦截器)

②特有拦截器(只有在 new 实例时传入的对象中传入了拦截器)

# 实现代码

在用 cli 脚手架创建完成项目后

在 src 下面创建 network 文件夹,在里面创建 index.ts

该文件是拿到 axios 请求封装实例并导出使用(网络请求出口)

// src/network/index.ts
//network 的统一出口
import NWRequest from './request'
// 这里是有传入特有拦截器的实例
const nwRequest = new NWRequest({
  baseURL: process.env.VUE_APP_BASE_URL,
  timeout: process.env.VUE_APP_TIME_OUT,
  interceptors: {
    requestInterceptor: (config: any) => {
      //console.log (' 在 new 实例时有传入拦截器的实例才有的拦截器:请求成功的拦截 ')
      // 携带 token 的拦截
      const token = localStorage.geiItem('token')
      if (token) {
        config.headers.Authorization = `Bearer ${token}`
      }
      return config
    },
    requestInterceptorCatch: (err) => {
      //console.log (' 在 new 实例时有传入拦截器的实例才有的拦截器:请求失败的拦截 ')
      return err
    },
    responseInterceptor: (config) => {
      //console.log (' 在 new 实例时有传入拦截器的实例才有的拦截器:响应成功的拦截 ')
      return config
    },
    responseInterceptorCatch: (err) => {
      //console.log (' 在 new 实例时有传入拦截器的实例才有的拦截器:响应失败的拦截 ')
      return err
    }
  }
})
export { nwRequest }

在 src 的 network 下创建 request 文件夹,在里面创建 type.ts

该文件是为了定义 ts 的限制类型接口 interface

import type { AxiosRequestConfig, AxiosResponse } from 'axios'
interface NWRequestInterceptors<T = AxiosResponse> {
  requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
  requestInterceptorCatch?: (error: any) => any
  responseInterceptor?: (res: T) => T
  responseInterceptorCatch?: (error: any) => any
}
interface NWRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
  interceptors?: NWRequestInterceptors<T>
}
export { NWRequestInterceptors, NWRequestConfig }

在 src 的 network 下的 request 文件夹,在里面创建 index.ts

该文件是 axios 主要封装类

import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { NWRequestInterceptors, NWRequestConfig } from './type'
// 定义网络请求的封装类
class NWRequest {
  instance: AxiosInstance
  interceptors?: NWRequestInterceptors
  constructor(config: NWRequestConfig) {
    this.instance = axios.create(config)
    this.interceptors = config.interceptors
    // 从 config 中取出的拦截器是对应的实例的拦截器
    // 只有 new 实例的时候有传入拦截器才有
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )
    // 添加所有的实例都有的拦截器
    this.instance.interceptors.request.use(
      (config) => {
        //console.log (' 所有的实例都有的拦截器:请求成功拦截 ')
        return config
      },
      (err) => {
        //console.log (' 所有的实例都有的拦截器:请求失败拦截 ')
        return err
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
        //console.log (' 所有的实例都有的拦截器:响应成功拦截 ')
        return res.data
      },
      (err) => {
        //console.log (' 所有的实例都有的拦截器:响应失败拦截 ')
        return err
      }
    )
  }
  request(config: NWRequestConfig): Promise<any> {
    return new Promise((resolve, reject) => {
      this.instance
        .request(config)
        .then((res) => {
          resolve(res)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }
  get(config: NWRequestConfig) {
    return this.request({
      ...config,
      method: 'GET'
    })
  }
  post(config: NWRequestConfig) {
    return this.request({
      ...config,
      method: 'POST'
    })
  }
}
export default NWRequest

# 测试

在 src 下的 main.ts 中

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { nwRequest } from './network'
const app = createApp(App)
app.use(router)
app.use(store)
app.mount('#app')
nwRequest
  .post({
    url: '/login',
    data: {
      name: '哈哈哈',
      password: '123456'
    }
  })
  .then((res) => {
    console.log(res)
  })

请我喝[茶]~( ̄▽ ̄)~*

呆头鸭 微信支付

微信支付

呆头鸭 支付宝

支付宝