您现在的位置是:首页 >技术教程 >【Axios、TypeScript】基于vue3和typescript的axios二次封装网站首页技术教程
【Axios、TypeScript】基于vue3和typescript的axios二次封装
简介【Axios、TypeScript】基于vue3和typescript的axios二次封装
准备
- 创建vue3项目
- 在 src 的文件下创建 发送网络请求相关的 文件夹 ?️
service
?️ service 包含有:
- index.ts 统一的出口
- ? request 用于封装axios网络请求
- ? modules 模块发送网络请求
- ? config 配置项
- 用于测试发送 网络请求的 api
- 历史上的今天 https://api.oioweb.cn/api/common/history
- 每日一句英文 https://api.oioweb.cn/doc/common/OneDayEnglish - 推荐使用 直课堂公开的api http://www.zkt-it.com:5050/jiekou/?target_id=001
- baseURL: http://www.zkt-it.com:5050
? request
?️ index.ts
使用 class
把封装 axios 封装成一个类,导出这个类
类型问题:
axios.create类型:
拦截器类型问题:
封装代码
import axios from 'axios'
import type { AxiosInstance } from 'axios'
// 拦截器:loading、token、修改配置
// AxiosRequestConfig类型中没有 interceptors 需要扩展类型
import PKRequestConfig from './type'
class PKRequest {
instance: AxiosInstance
constructor(config: PKRequestConfig) {
// 每个实例都会 创建axios
this.instance = axios.create(config)
// 实例 全局的拦截器
this.instance.interceptors.request.use(
(config) => {
console.log('实例-> 全局的请求成功的拦截:')
return config
},
(err) => {
console.log('实例-> 全局的请求失败的拦截:')
return err
}
)
this.instance.interceptors.response.use(
(res) => {
console.log('实例-> 全局的响应成功的拦截:')
// res.data => promise的res类型有问题 : 通过泛型解决
return res
},
(err) => {
console.log('实例-> 全局的响应失败的拦截:')
return err
}
)
// 针对特定的pkRequest实例添加拦截
this.instance.interceptors.request.use(
config.interceptors?.requestSuccessFn,
config.interceptors?.requestFailedFn
)
this.instance.interceptors.response.use(
config.interceptors?.reponseSuccessFn,
config.interceptors?.reponseFailedFn
)
}
// 网络请求泛型; 因为promise的成功的回调 返回的类型 是创建实例时确定的
// PKRequestConfig<T> : PKRequestConfig中的拦截器 响应成功的返回数据类型需要和 promise一致
request<T = any>(config: PKRequestConfig<T>) {
// 针对网络请求 中,有 拦截器
if (config.interceptors?.requestSuccessFn) {
// 单次请求的成功拦截
config.interceptors.requestSuccessFn(config as any)
}
// 返回的promise
return new Promise<T>((resolve, reject) => {
this.instance
.request<any, T>(config)
.then((res) => {
if (config.interceptors?.reponseSuccessFn) {
res = config.interceptors.reponseSuccessFn(res)
}
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
get<T = any>(config: PKRequestConfig<T>) {
return this.request({ ...config, method: 'GET' })
}
post<T = any>(config: PKRequestConfig<T>) {
return this.request({ ...config, method: 'POST' })
}
delete<T = any>(config: PKRequestConfig<T>) {
return this.request({ ...config, method: 'DELETE' })
}
put<T = any>(config: PKRequestConfig<T>) {
return this.request({ ...config, method: 'PUT' })
}
patch<T = any>(config: PKRequestConfig<T>) {
return this.request({ ...config, method: 'PATCH' })
}
}
export default PKRequest
import type { AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
// 扩展 AxiosRequestConfig类型
interface PKInterceptors<T = AxiosResponse> {
requestSuccessFn?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig
requestFailedFn?: (err: any) => any
reponseSuccessFn?: (res: T) => T
reponseFailedFn?: (err: any) => any
}
interface PKRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: PKInterceptors<T>
}
export default PKRequestConfig
? config
?️ index.ts 主要写配置
export const BASE_URL = 'http://www.zkt-it.com:5050'
export const TIME_OUT = 10000
// 测试登录获取token
export const BASE_URL2 = 'http://codercba.com:5000'
? index.ts
创建 PKRequest 的实例。实例可以有多个
例如:
import PKRequest from './request'
import { BASE_URL, TIME_OUT } from './config/index'
// pkRequest实例
const pkRequest = new PKRequest({
baseURL: BASE_URL,
timeout: TIME_OUT
})
// 实例2
export const pkRequest2 = new PKRequest({
baseURL: 'https://api.oioweb.cn/api/common',
timeout: 8000,
// 单独的拦截器
// AxiosRequestConfig类型中没有 interceptors
interceptors: {
requestSuccessFn: (config) => {
console.log('pkRequest2单独拦截器:请求成功的拦截')
return config
},
requestFailedFn: (err) => {
console.log('pkRequest2单独拦截器:请求失败的拦截')
return err
},
reponseSuccessFn: (res) => {
console.log('pkRequest2单独拦截器:响应成功的拦截')
return res
},
reponseFailedFn: (err) => {
console.log('pkRequest2单独拦截器:响应失败的拦截')
return err
}
}
})
// 实例3:登录 BASE_URL2
export const pkRequest3 = new PKRequest({
baseURL: BASE_URL2,
timeout: 3000
})
export default pkRequest
? module
?️ index.ts
import('./home')
import('./year')
import('./gettest')
import('./login')
?️ home.ts
import pkRequest from '..'
// home.ts
// 根据请求数据设置数据类型
interface INews {
data: any[]
status: number
statusText: string
config: object
headers: any
request: any
}
pkRequest
.request<INews>({
url: '/news'
})
.then((res) => {
// 通过泛型设置,此时的res类型为 INews
console.log('pkRequest1:新闻', res.data, res.status)
})
pkRequest
.request({ //没有特别写类型,则是泛型的默认值 any
url: '/mingxing',
interceptors: {
requestSuccessFn: (config) => {
console.log('/mingxing 请求成功的拦截 :')
return config
},
reponseSuccessFn: (res) => {
console.log('/mingxing 响应成功的拦截 :')
return res
}
}
})
.then((res) => {
console.log('pkRequest1:明星', res)
})
?️ year.ts
import { pkRequest2 } from '..'
// year.ts
pkRequest2
.request({
url: '/history'
})
.then((res) => {
console.log('pkRequest2:历史上的今天', res)
})
?️ login.ts
import { pkRequest3 } from '..'
const postLoginRequest = async () => {
const res = await pkRequest3.post({
url: '/login',
data: {
name: 'coderwhy',
password: '123456'
}
})
console.log('登录用户信息:')
console.table(res.data.data)
}
postLoginRequest()
输出结果
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。