跨域是一个老生常谈的问题,不再过多的去解释什么是跨域了,着重记录在React项目中怎么去解决跨域,当然对于前端开发而言,绝大部分的跨域问题,都是通过代理的方式解决的!
而代理适用的场景是:在生产环境中不发生跨域,但在开发环境中会发生跨域!因此,我们只需要在开发环境中使用前端代理解决跨域即可,又称为开发代理!
在React中解决跨域,毫无疑问,也是使用开发代理解决!
目录
产生跨域问题
解决跨域问题:
简单方式:
复杂方式:
产生跨域问题
举例,我们需要在React项目中使用axios,请求这个网址拿数据
https://h5.ele.me/restapi/bgs/poi/reverse_geo_coding?latitude=34.60614175850704&longitude=112.43507808743286
import React, {Component} from 'react';
import axios from "axios";
class App extends Component {
getData = async () => {
const resp = await axios.get('https://h5.ele.me/restapi/bgs/poi/reverse_geo_coding?latitude=34.60614175850704&longitude=112.43507808743286')
console.log(resp)
}
render() {
return (
<div>
<button onClick={this.getData}>获取数据</button>
</div>
);
}
}
export default App;
页面点击获取数据,在控制台上就会出现如下情况,毫无疑问,这是出现了跨域问题
解决跨域问题:
简单方式:
第一步:在react项目中,找到package.json文件,打开它,在里面添加如下代码!
第二步:将axios请求地址更改如下:
/restapi/bgs/poi/reverse_geo_coding?latitude=34.60614175850704&longitude=112.43507808743286
第三步:重新启动项目,测试是否解决跨域
getData = async () => {
const resp = await axios.get('/restapi/bgs/poi/reverse_geo_coding?latitude=34.60614175850704&longitude=112.43507808743286')
console.log(resp)
}
点击效果如下:跨域已解决!
说下这种解决方式的优缺点:
优点:肉眼可见的简单
缺点:只能配置一个,当我的项目中有多个请求域名时,无法解决。。。
复杂方式:
第一步:找到src目录,在src下新建setupProxy.js文件
第二步:在setupProxy.js中配置具体的代理规则,在这里需要注意一下,你需要知道自己用的是React18最新的版本或者是React17的版本
React18:
//需要采用CommonJS的写法
const {createProxyMiddleware} = require('http-proxy-middleware')
module.exports = function (app) {
app.use(createProxyMiddleware('/api-elm', //遇见/api-elm前缀的请求,就会触发该代理配置
{
target: 'https://h5.ele.me', //请求转发给谁(能返回数据的服务器地址)
changeOrigin: true, //控制服务器收到的响应头中Host字段的值
pathRewrite: {'^/api-elm': ''} //重写请求路径,保证交给后台服务器是正常地请求地址(必须配置)
}),
createProxyMiddleware('/api-news',
{
target: 'https://pacaio.match.qq.com',
changeOrigin: true,
pathRewrite: {'^/api-news': ''}
}))
}
React17:当你使用的是React18版本,但却是采用17的写法,那么会发现你的react项目无法连接,拒绝访问。。。
//需要采用CommonJS的写法
const proxy = require('http-proxy-middleware')
module.exports = function (app) {
app.use(proxy('/api-elm', //遇见/api-elm前缀的请求,就会触发该代理配置
{
target: 'https://h5.ele.me', //请求转发给谁(能返回数据的服务器地址)
changeOrigin: true, //控制服务器收到的响应头中Host字段的值
pathRewrite: {'^/api-elm': ''} //重写请求路径,保证交给后台服务器是正常地请求地址(必须配置)
}),
proxy('/api-news',
{
target: 'https://pacaio.match.qq.com',
changeOrigin: true,
pathRewrite: {'^/api-news': ''}
}))
}
特别说明:setupProxy.js不需要去引入到任何文件,在开发运行的时候,会自动帮我们注册
第三步:修改组件请求代码,重启项目
import React, {Component} from "react";
import axios from "axios";
class App extends Component {
getAddressData = () => {
axios.get('/api-elm/restapi/bgs/poi/reverse_geo_coding?latitude=34.841673&longitude=113.675712').then(resp => {
console.log(resp)
}).catch(err => {
console.log(err)
})
}
getNewsData = async () => {
const response = await axios.get('/api-news/irs/rcd?page=1&num=20&expIds=20220620V0103G00%7C20220620V017LK00%7C20220617V098W60&cid=56&ext=sports_nba&token=c786875b8e04da17b24ea5e332745e0f')
console.log(response)
}
render() {
return (
<div>
<button onClick={this.getAddressData}>获取地址数据</button>
<button onClick={this.getNewsData}>获取新闻数据</button>
</div>
);
}
}
export default App;
点击效果如下:
说下这种解决方式的优缺点:
优点:可以配置多个代理,可以灵活的控制请求是否需要走代理。
缺点:配置比较繁琐,前端请求资源时必须加前缀。