1、前言
因为最近在进行老系统用新框架改造,正好用到了react,就顺便整理了一下react中对axios进行封装的相关知识点和步骤。
2、如何封装
可以参考一下chat gpt给出的回答。
我大概总结一下,其实就是使用axios.create创建一个axios的实例,然后我们每次发get/post请求,都直接调用这个创建好的axios实例就行了。
3、相关代码
相关代码gitee地址:https://gitee.com/wulinchun/my-react-ts.git
Step1、创建一个typescript的react工程项目 。
npx create-react-app my-react-ts --template typescript
如果不加 --template typescript,react默认建的是javascript工程。我之前去网上学习react的时候,许多教程都是基于js,jsx创建的react工程,但我在公司开发的react项目都是typescript的。typescript是javascript的增强版,我之前一直都是写javascript、jquery这套的,typescript之前没接触过。我没怎么系统学习过typescript语言,就我在实际工作开发而言。typescript增加了一些结构类型的定义。比如我在.ts里面可以定义一个interface结构用于接收后端的数据,interface结构中我可以详细的定义每一个变量的类型:string,number,boolean等等。不确定的类型则用any。相比较而言javascript就没这么强大。typescript的编译比javascript严格。javascript是弱类型的,只要不是什么涉及到计算的,你把一个字符串型的数值赋值给一个数值类型的变量也没啥问题。你直接用var定义就行了。但typescript就不可以了。
不过从编译效率上来说的话,因为node.js不能直接执行.ts文件,因此编译的时候会多一步把typescript转为javascript,因此typescript要比javascript慢一点。
关于typescript更多的了解可参考:
TypeScript 与 JavaScript:你应该知道的区别 - 掘金 (juejin.cn)
文档简介 · TypeScript中文网 · TypeScript——JavaScript的超集 (tslang.cn)
Step2、react前端代码
这是我的工程目录结构
request.ts(用于封装axios实例)
import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import axios from 'axios'
interface AxiosTokenInstance extends AxiosInstance {
}
// 创建一个axios实例
const instance: AxiosTokenInstance = axios.create({
baseURL: '/',
timeout: 5000,
responseType: 'json',
headers: {
'Content-Type': 'application/json',
},
})
const {request,get,post} = instance;
//暴露axios实例
export {request,get,post,instance};
returnType.ts(接口返回值数据结构)
export interface ResType<R>{
code:number;
message:string;
data:R;
}
setupProxy.js(配置代理,注意必须是.js代理文件,不能用setupProxy.ts,因为npm start启动的时候无法加载.ts的配置文件)
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://127.0.0.1:80',
changeOrigin: true,
pathRewrite: {
'^/api': '',
}
})
);
app.use(
'/api1',
createProxyMiddleware({
target: 'http://localhost:8082',
changeOrigin: true,
pathRewrite: {
'^/api1': '',
}
})
);
};
src\pages\Home\index.tsx(页面组件)
import React,{useState} from "react";
import {PeopleDTO,listAllPeople,getPeople,getPeople1,PeopleV2DTO} from './service'
import {useRequest} from 'ahooks';
const Home:React.FC=()=>{
const [peopleDTOList,setpeopleDTOList]=useState<PeopleDTO[]>([]);
const [age,setAge]=useState('')
const [peopleId,setPeopleId]=useState('')
const [peopleName,setPeopleName]=useState('')
const [position,setPosition]=useState('')
const [subordinateList,setSubordinateList]=useState<PeopleV2DTO[]>([]);
const [searchContent, setSearchContent] = useState<string>('');
const listPeople=()=>{
//get请求无参数
listAllPeople().then((response) => {
const result = response.data;
console.log(response);
console.log(result);
setpeopleDTOList(result.PeopleDTOList);
console.log(peopleDTOList)
});
};
const getOnePeople=()=>{
//get请求带参数
getPeople(searchContent).then((response) => {
console.log(searchContent)
const result = response.data;
console.log(response);
console.log(result);
setAge(result.age);
setPeopleId(result.peopleId);
setPeopleName(result.peopleName);
setPosition(result.position);
setSubordinateList(result.subordinate);
});
};
const getOnePeople1=()=>{
//post请求带json参数
getPeople1({PeopleId:searchContent}).then((response) => {
console.log(searchContent)
const result = response.data;
console.log(response);
console.log(result);
setAge(result.age);
setPeopleId(result.peopleId);
setPeopleName(result.peopleName);
setPosition(result.position);
setSubordinateList(result.subordinate);
});
};
return(
<div>
<h1>首页</h1>
<button onClick={() => listPeople()}>listAllPeople</button>
<input
placeholder="请输入待搜索人员"
value={searchContent}
onChange={(e) => {
setSearchContent(e.target.value);
}}
/>
<button onClick={() => getOnePeople()}>getOnePeople</button>
<button onClick={() => getOnePeople1()}>getOnePeople1</button>
<table>
<tbody>
{peopleDTOList.map((items, index)=>(
<tr key={index}>
<th>ID:</th><td>{items.peopleId}</td>
<th>姓名:</th><td>{items.peopleName}</td>
<th>年龄:</th><td>{items.age}</td>
<th>职位:</th><td>{items.position}</td>
<th>下属:</th>
<td>
{items.subordinate.map((it,idx)=>(
<label key={idx}>{it.name}~{it.age}</label>
))}
</td>
</tr>
))}
</tbody>
</table>
</div>
)
};
export default Home;
src\pages\Home\service.ts(定义数据结构以及请求后端接口)
import { get,post } from '../../../src/utils/request';
import {ResType} from '../../../src/utils/returnType'
export interface PeopleDTO {
peopleId: string;
peopleName: string;
age: string;
position: string;
subordinate: PeopleV2DTO[];
}
export interface PeopleV2DTO {
name: string;
age: string;
}
export interface PeopleDTOList{
PeopleDTOList: PeopleDTO[];
}
export interface PeopleId{
PeopleId: string;
}
export const listAllPeople:(
) =>Promise<ResType<PeopleDTOList>>=()=>{
return get('api/root/listPeople.asp')
}
export const getPeople:(
params:string,
) =>Promise<ResType<PeopleDTO>>=(params)=>{
return get(`api/root/getPeople.asp?PeopleId=${params}`,{})
};
export const getPeople1:(
params:PeopleId,
) =>Promise<ResType<PeopleDTO>>=(params)=>{
return post('api1/login/getPeople1',params)
};
src\index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Home from './pages/Home';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
{/* <App /> */}
<Home/>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
Step3、后端接口
vbscript接口,部署在http://127.0.0.1:80上
1、/root/listPeople.asp
<%
Response.Charset="utf-8"
Set util=CreateObject("util.WSC")
Set bzExample=CreateObject("bzExample.WSC")
Set oJsonResponse = util.InitAspJson()
ReDim Preserve arrDetail(2,3)
arrDetail(0,0)="李五"
arrDetail(1,0)="20"
arrDetail(0,1)="王五"
arrDetail(1,1)="22"
arrDetail(0,2)="赵六"
arrDetail(1,2)="25"
'Response.Write Ubound(arrDetail,2)&"<br/>"
With oJsonResponse.data
.Add "PeopleDTOList",oJsonResponse.Collection()
With .item("PeopleDTOList")
.Add 0,oJsonResponse.Collection()
With .item(0)
.Add "peopleId","zhangsan"
.Add "peopleName","张三"
.Add "age","30"
.Add "position","Manager"
.Add "subordinate",oJsonResponse.Collection()
With .item("subordinate")
indexI = 0
for indexI=0 to Ubound(arrDetail,2)-1
'Response.Write "indexI="&indexI&"<br/>"
.Add indexI,oJsonResponse.Collection()
With .item(indexI)
.Add "name",arrDetail(0,indexI)
.Add "age",arrDetail(1,indexI)
End With
'indexI = indexI +1
next
End With
End With
.Add 1,oJsonResponse.Collection()
With .item(1)
.Add "peopleId","lisi"
.Add "peopleName","李四"
.Add "age","40"
.Add "position","Manager"
.Add "subordinate",oJsonResponse.Collection()
With .item("subordinate")
indexI = 0
for indexI=0 to Ubound(arrDetail,2)-1
'Response.Write "indexI="&indexI&"<br/>"
.Add indexI,oJsonResponse.Collection()
With .item(indexI)
.Add "name",arrDetail(0,indexI)
.Add "age",arrDetail(1,indexI)
End With
'indexI = indexI +1
next
End With
End With
End With
End With
Response.Write oJsonResponse.JSONoutput()
%>
2、/root/getPeople.asp
<%
Response.Charset="utf-8"
Set util=CreateObject("util.WSC")
Set bzExample=CreateObject("bzExample.WSC")
Set oJsonResponse = util.InitAspJson()
peopleId=request("PeopleId")
ReDim Preserve arrDetail(2,3)
arrDetail(0,0)="李五"
arrDetail(1,0)="20"
arrDetail(0,1)="王五"
arrDetail(1,1)="22"
arrDetail(0,2)="赵六"
arrDetail(1,2)="25"
'Response.Write Ubound(arrDetail,2)&"<br/>"
With oJsonResponse.data
if peopleId="zhangsan" then
.Add "peopleId","zhangsan"
.Add "peopleName","张三"
.Add "age","30"
.Add "position","Manager"
.Add "subordinate",oJsonResponse.Collection()
With .item("subordinate")
indexI = 0
for indexI=0 to Ubound(arrDetail,2)-1
'Response.Write "indexI="&indexI&"<br/>"
.Add indexI,oJsonResponse.Collection()
With .item(indexI)
.Add "name",arrDetail(0,indexI)
.Add "age",arrDetail(1,indexI)
End With
'indexI = indexI +1
next
End With
end if
if peopleId="lisi" then
.Add "peopleId","lisi"
.Add "peopleName","李四"
.Add "age","40"
.Add "position","Manager"
.Add "subordinate",oJsonResponse.Collection()
With .item("subordinate")
indexI = 0
for indexI=0 to Ubound(arrDetail,2)-1
'Response.Write "indexI="&indexI&"<br/>"
.Add indexI,oJsonResponse.Collection()
With .item(indexI)
.Add "name",arrDetail(0,indexI)
.Add "age",arrDetail(1,indexI)
End With
'indexI = indexI +1
next
End With
end if
End With
Response.Write oJsonResponse.JSONoutput()
%>
java接口,部署在http://localhost:8082上
1、/login/getPeople1
@PostMapping("/getPeople1")
@ResponseBody
public PeopleDTO getPeople1(@RequestBody Map<String, Object> map) {
String peopleId = map.get("PeopleId").toString();
PeopleDTO peopleDTO1 = new PeopleDTO("zhangsan", "张三", "30", "Manager", null);
PeopleDTO peopleDTO2 = new PeopleDTO("lisi", "李四", "40", "Manager", null);
PeopleV2DTO peopleV2DTO1 = new PeopleV2DTO("李五", "20");
PeopleV2DTO peopleV2DTO2 = new PeopleV2DTO("王五", "22");
PeopleV2DTO peopleV2DTO3 = new PeopleV2DTO("赵六", "25");
List<PeopleV2DTO> peopleV2DTOList = Arrays.asList(peopleV2DTO1, peopleV2DTO2, peopleV2DTO3);
peopleDTO1.setSubordinate(peopleV2DTOList);
peopleDTO2.setSubordinate(peopleV2DTOList);
if (peopleId.equals("zhangsan")) {
return peopleDTO1;
}
if (peopleId.equals("lisi")) {
return peopleDTO2;
}
return null;
}
运行效果
4、总结
前端进行http请求后端接口可以有三个选择:ajax,axios和fetch。ajax普遍用于jquery中的。axios和fetch都是用于vue,react之类的前端主流框架。更推荐使用axios而不是fetch,因为fetch比较老,对浏览器的兼容性不如axios。并且由于fetch是偏向于底层原生的嘛。所以fetch所提供的功能不如axios强大。
axios与fetch比较可以参考一下这篇:Axios or fetch():你更中意哪一个? - 掘金 (juejin.cn)
简单概括一下 axios与fetch的差异:
- axios对浏览器的兼容性比fetch更广。
- axios的返回值可以自动转为json格式,但fetch会返回一个包含响应结果的promise,所以fetch需要手动使用json()方法进行一个转换。
- axios在一些基础配置使用上,比如配置拦截器,配置响应超时时间,同时发起多个响应请求上要比fetch更加快捷方便。
在实际使用axios过程中,都会倾向于先对axios进行一个封装。统一配置像baseURL、timeout、responseType、headers等等属性,以便于开箱即用。
5、参考资料
最新React使用 http-proxy-middleware解决多跨域问题(完美篇)_晴天小哥哥的博客-CSDN博客
yarn npm 设置淘宝镜像_AlbertGou的博客-CSDN博客
TypeScript 与 JavaScript:你应该知道的区别 - 掘金
java后台接收json数据_json对象,后端实体类怎么接_随影随行的博客-CSDN博客
TypeScript中文网 · TypeScript——JavaScript的超集