本文主要介绍了vue3和typescript+vite实际开发中对axios的请求封装
1.目录划分
在我们实际开发中,通常会对不同功能进行不同的目录结构划分
例如:网路请求我们通常会封装到api目录下面,然后里面分模块modules以及类型types、axios配置等
2.请求配置
axios请求时,一般会配置baseUrl,timeout等,我们可以把这些固定的配置项放到config.ts文件里,然后导出
let BASE_URL = ''
const TIME_OUT = 10000
if (process.env.NODE_ENV === 'development') {
BASE_URL = 'XXXXXXXXX'
} else if (process.env.NODE_ENV === 'production') {
BASE_URL = 'XXXXXXXXX'
}
const AXIOS_BASE_CONFIG = {
baseURL: BASE_URL,
timeOut: TIME_OUT,
heard: {
'Content-Type': 'application/json; charset=utf-8',
},
}
export { BASE_URL, AXIOS_BASE_CONFIG }
3.axios封装
import axios from 'axios'
import qs from 'qs'
import { AXIOS_BASE_CONFIG } from './config'
import type { AxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios'
import { message } from 'ant-design-vue'
import * as TYPES from '@/types/mutation-type'
import useStorage from '@/hooks/useStorage'
type axiosResponse<T = any> = {
Message: string
ResultCode: number
Success: boolean
Tag: T
TotalRecord: string | number
}
const { getStorage } = useStorage()
const handleError = (error: any) => {
const {
data: { Message },
} = error.response
message.destroy()
message.error(Message ? Message : '请求失败,请重新刷新页面')
return Promise.reject(error)
}
class Request {
private instance: AxiosInstance
constructor(config: AxiosRequestConfig = {}) {
this.instance = axios.create({ ...AXIOS_BASE_CONFIG, ...config })
this.initInstance()
}
/**
* @method 初始化拦截器
*/
private initInstance() {
/**
* @method 请求拦截器
*/
this.instance.interceptors.request.use((config: AxiosRequestConfig) => {
const _token = getStorage('session', TYPES.ASSESS_TOKEN)
if (_token) {
config.headers!.common['Authorization'] = _token
}
if (['GET', 'get'].includes(config.method!)) {
config.url += '?' + qs.stringify(config.data ?? '')
}
return config
}, handleError)
/**
* @method 响应拦截器
*/
this.instance.interceptors.response.use((response: AxiosResponse<axiosResponse>) => {
if (!response.data.Success) {
message.error(response.data.Message ?? '系统异常')
if ([403, 505].includes(response.data.ResultCode)) {
setTimeout(() => {
window.location.replace(window.location.origin)
}, 500)
}
return Promise.reject(response.data)
}
return Promise.resolve(response.data)
}, handleError)
}
/**
* @method 请求
* @param config 请求配置项
*/
private request<D = any>(config: AxiosRequestConfig) {
return new Promise<axiosResponse<D>>(async (resolve, reject) => {
try {
const res = await this.instance.request<axiosResponse<D>, axiosResponse<D>>(config)
resolve(res)
} catch (error) {
console.log('error', error)
reject(error)
}
})
}
/**
* @method GET请求
* @param config 请求配置项
*/
public GET<R>(config: AxiosRequestConfig) {
return this.request<R>({ ...config, method: 'GET' })
}
/**
* @method POST请求
* @param config 请求配置项
*/
public POST<R>(config: AxiosRequestConfig) {
return this.request<R>({ ...config, method: 'POST' })
}
/**
* @method PUT请求
* @param config 请求配置项
*/
public PUT<R>(config: AxiosRequestConfig) {
return this.request<R>({ ...config, method: 'PUT' })
}
/**
* @method DELETE请求
* @param config 请求配置项
*/
public DELETE<R>(config: AxiosRequestConfig) {
return this.request<R>({ ...config, method: 'DELETE' })
}
}
export default Request
4.使用
import request from '@/service'
const http = new request()
type dictionaryType = {
name: string
code: string
id: string | number
nameAdCode?: string
nameAndCode?: string
value?: string
label?: string
}
enum roadWayApiEnum {
tunnelFindDropDown = 'XXX/XXXXX/XXXXX'
}
export const tunnelFindDropDown = (data: any) => http .POST<dictionaryType[]>({ url: roadWayApiEnum.tunnelFindDropDown, data })
import { regionFindDropDown } from '@/service/modules/roadWay_api'
async function initRegionOption() {
const { Tag, Success } = await regionFindDropDown({ id: formState.value.id})
if (Success) {
Tag.forEach((item) => {
item.nameAdCode = `【${item.code}】${item.name}`
})
wholeOptions.regionOptions = Tag
}
}
按照我们这样封装后,在调用请求时传入Tag的泛型,我们解构出来的Tag直接就是这个类型