React 中的跨域配置和 axios、fetch 的使用

react 脚手架中的跨域配置

方法一

在 package.json 中追加如下配置

1
"proxy":"http://localhost:5000"

说明

  1. 优点:配置简单,前端请求资源时可以不加任何前缀。
  2. 缺点:不能配置多个代理。
  3. 工作方式:上述方式配置代理,当请求了 3000 不存在的资源时,那么该请求会转发给 5000 (优先匹配前端资源)

方法二

第一步:创建代理配置文件

在 src 下创建配置文件:src/setupProxy.js

第二步:编写 setupProxy.js 配置具体代理规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const proxy = require('http-proxy-middleware')

module.exports = function (app) {
app.use(
// 配置多个代理
proxy('/api1', {
//api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
changeOrigin: true, //控制服务器接收到的请求头中host字段的值
/*
1.changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
2.changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
3.changeOrigin默认值为false,但我们一般将changeOrigin值设为true
*/
pathRewrite: { '^/api1': '' }, //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
}),
proxy('/api2', {
target: 'http://localhost:5001',
changeOrigin: true,
pathRewrite: { '^/api2': '' },
})
)
}

说明:

  1. 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
  2. 缺点:配置繁琐,前端请求资源时必须加前缀。

发送请求

1
2
3
4
5
6
7
8
9
10
11
12
// 发送请求的方法:
getData = () => {
// 由3000发起请求,请求的是3000(代理),由代理转发给localhost:5000/list
axios.get('http://localhostL:3000/api1/student').then(
(response) => {
console.log('成功了'), response.data
},
(error) => {
console.log('失败了', error.message)
}
)
}

总结

1
2
3
4
5
6
1、安装axios
npm install axios
2、在需要使用axios的文件中导入:
import axios from 'axios'
3、在src/setProxy.js中配置代理
4、发起请求

antd-pro 脚手架中配置跨域

第一步:在 config.js/proxy.js 中配置代理规则

1
2
3
4
5
6
7
8
9
10
export default {
dev: {
// 将带有api前缀的请求发送给http://localhost:3000/api
'/api': {
tagget: 'http://localhost:3000/api',
chageOrigin: true,
pathRewrite: { '^/api': '' },
},
},
}

第二步:发送请求

  1. 安装 axios:npm install axios

  2. 引入 axios:import axios from ‘axios’

  3. 使用 axios

1
2
3
4
5
6
7
8
9
10
11
componentDidMount() {
// 由8000端口发起请求,代理向localhost:3000/api/list发送请求,获取并返回数据
axios.get('http://localhost:8000/api/list').then(
res=>{
console.log("success.........",res.data);
},
error=>{
console.log("error..........",error.message);
}
)
}

fetch

案例源码:fetch 案例–github 用户搜索

发送网络请求 — 使用 fetch 发送 (未优化)

then () 方法返回一个 Promise (en-US)。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
search = () => {
const { keyWordEl: { value: keyWord } } = this
PubSub.publish('aiguigu', { isFirst: false, isLoading: true })
fetch(`/api1/search/users?q=${keyWord}`).then(
response => {
console.log('联系服务器成功---能和服务器建立对话,不确定能不能获取数据');
return response.json()// 返回 promise实例对象
},
error => {
// console.log('联系服务器失败---服务器离线或其他因素', error);
// 中断Promise链
// return new Promise(() => { })
}
).then(
response => {
console.log('获取数据成功', response);
},
// error => {
// console.log('获取数据失败', error);
// }
).catch(
(error) => { console.log(error); }
)
}

render() {
return (
<section className="jumbotron">
<h3 className="jumbotron-heading">搜索 Github 用户</h3>
<div>
<input ref={c => this.keyWordEl = c} type="text" placeholder="输入关键词点击搜索" />
&nbsp;
<button onClick={this.search}>搜索</button>
</div>
</section>
);
}

发送网络请求 — 使用 fetch 发送 (优化)

fetch 关注分离的设计思想 原生函数不使用 XHR 兼容性不高
需要在 search 上加 async

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
search = async () => {
const { keyWordEl: { value: keyWord } } = this
PubSub.publish('aiguigu', { isFirst: false, isLoading: true })
try {
const response = await fetch(`/api1/search/users?q=${keyWord}`)
const data = await response.json()
PubSub.publish('aiguigu', { isFirst: false, isLoading: false, users: data.items })
} catch (error) {
PubSub.publish('aiguigu', { isFirst: false, isLoading: false, err: error.message })
}
}

render() {
return (
<section className="jumbotron">
<h3 className="jumbotron-heading">搜索 Github 用户</h3>
<div>
<input ref={c => this.keyWordEl = c} type="text" placeholder="输入关键词点击搜索" />
&nbsp;
<button onClick={this.search}>搜索</button>
</div>
</section>
);
}

对比 发送网络请求 — 使用 axios 发送

1
2
3
4
5
6
7
8
9
10
axios.get(`/api1/search/users?q=${keyWord}`).then(
// 请求成功通知app更新状态
response => {
PubSub.publish('aiguigu', { isFirst: false, isLoading: false, users: response.data.items })
},
// 请求失败通知app更新状态
error => {
PubSub.publish('aiguigu', { isFirst: false, isLoading: false, err: error.message })
}
)