文章目录
- React Ajax
- Axios
- 在 React 中使用 Axios
- 脚手架代理配置
React Ajax
-
理解
- React 本身只关注于界面,并不包含发送 ajax 请求的代码。
- 前端应用需要通过 ajax 请求与后台进行交互(json 数据)。
- React 应用中需要继承第三方 ajax 库(或自己封装)。
-
常用 ajax 请求库
- jQuery:比较重,如果需要另外引入,不建议使用。
- axios:轻量级,推荐使用
Axios
Axios 是一个基于 promise 的网络请求库,可以用于浏览器和 node.js。
在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
-
特性
- 从浏览器创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防御 XSRF
-
安装
- npm 安装命令:
npm install axios
- 通过 Yarn 安装:
yarn add axios
想学习和了解更多 axios 内容,请访问 Axios 中文网
在 React 中使用 Axios
通过一个简单的代码实例来演示,这里需要提前准备好两个 api 服务器,如果没有准备好,请阅读上一篇文章,代码如下:
// file: src/App.js
import React, { Component } from "react";
import axios from "axios"; // 导入 axios
export default class App extends Component {
getStudentData = () => {
axios.get("http://127.0.0.1:5000/students").then(
(response) => {
console.log("成功:", response.data);
},
(error) => {
console.log("失败:", error);
}
);
};
getCarsData = () => {
axios.get("http://127.0.0.1:5001/cars").then(
(response) => {
console.log("成功:", response.data);
},
(error) => {
console.log("失败:", error);
}
);
};
render() {
return (
<div>
<button onClick={this.getStudentData}>点我获取学生数据</button>
<button onClick={this.getCarsData}>点我获取汽车数据</button>
</div>
);
}
首先运行 node server1.js
和 node server2.js
命令,启动两台服务器;
然后运行 React 代码,点击界面上的【点我获取学生数据】按钮和【点击获取汽车数据】按钮,浏览器控制台都会报出如下跨域问题:
扩展
基于上面的问题,简单介绍一下跨域相关概念。
- 首先,什么是跨域呢?
跨域指的是浏览器不能执行其他网站的脚本,简单来说是浏览器同源政策的限制,浏览器针对于 ajax 的限制。- 同源政策
两个页面拥有相同的协议,端口,域名 就是同源,如果有一个不相同就是不同源。同源政策产生的目的是为了保护用户信息安全,防止一些网站盗取用户信息。
那么,在 React 中如何解决跨域的问题呢?这就引出了本文的正题,—— 代理。(当然还可以通过其他方式解决跨域问题,如 jsonp、nginx 反向代理等。)
脚手架代理配置
-
什么是代理
常说的代理就是一个代理服务器,例如 A 服务器请求 B 服务器,我们可以通过代理 C 服务器去帮助我们请求,产生的跨域原因就是浏览器的同源政策是针对于 ajax 的请求,并不限制服务器之间的通信传输,而这个代理服务器正是和我相同端口域名的,我只需去用代理服务器去发请求再去接收,从而达到跨域。 -
两种配置方式
-
方式一
在 package.json 中追加如下代码:"proxy": "http://127.0.0.1:5000"
说明:
- 优点:配置简单,前端请求资源时可以不加任何前缀。
- 缺点:不能配置多个代理。
- 工作方式:上述方式配置代理,当请求了 3000 不存在的资源,那么该请求会转发给 5000(优先匹配前端资源)。
实战:
-
首先,上面 App.js 中的 getStudentData 方法中 axios.get 第一个参数请求 url 中的 端口要改成 3000,代码如下:
getStudentData = () => { axios.get("http://127.0.0.1:3000/students").then( (response) => { console.log("成功:", response.data); }, (error) => { console.log("失败:", error); } ); };
-
然后,在 package.json 中第一层添加
"proxy": "http://127.0.0.1:5000"
,注意一定要不要写错位置了,可参照下面的截图:
-
最后,由于更改了 package.json 文件,需要运行
yarn start
重启 React 应用,代理才能起作用,此时在浏览器中打开的页面中点击【点我获取学生数据】按钮,就可以正常返回数据了,截图如下:
-
方式二
第一步,创建代理配置文件。在 src 下创建配置文件:src/setupProxy.js。
第二步,编写 setupProxy.js 配置具体代理规则:// file:src/setupProxy.js const proxy = require("http-proxy-middleware"); module.exports = function (app) { app.use( // /api1是需要转发的请求(所有带有/api前缀的请求都会转发给5000) proxy("/api1", { target: "http://127.0.0.1:5000", // 配置转发目标地址(能返回数据的服务器地址) changeOrigin: true, // 控制服务器接收到的请求头中Host字段的值 /* changeOrigin 设置为 true 时,服务器收到的请求头中的 host 为:localhost:5000 changeOrigin 设置为 false 时,服务器收到的请求头中的 host 为:localhost:3000 changeOrigin 默认为 true ,但我们一般将 changeOrigin 值设为 true */ pathRewrite: { "^/api1": "" }, // 重写请求路径,去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置) }), proxy("/api2", { target: "http://127.0.0.1:5001", changeOrigin: true, pathRewrite: { "^/api2": "" }, }) ); };
说明:
- 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
- 缺点:配置繁琐,前端请求资源时必须加前缀。
实战:
-
首先,确保已经在 src 下创建配置了 setupProxy.js 文件,且正确编写了代理规则;
-
然后,修改 App.js 中的 axios 请求地址,代码如下:
getStudentData = () => { axios.get("http://localhost:3000/api1/students").then( (response) => { console.log("成功:", response.data); }, (error) => { console.log("失败:", error); } ); }; getCarsData = () => { axios.get("http://localhost:3000/api2/cars").then( (response) => { console.log("成功:", response.data); }, (error) => { console.log("失败:", error); } ); };
-
最后,需要运行
yarn start
重启 React 应用,代理才能起作用,此时在浏览器中打开的页面中分别点击【点我获取学生数据】按钮和【点我获取汽车数据】按钮,就可以正常返回数据了,截图如下:
如果浏览器报错如下:
setupProxy VM200:6772 crbug/1173575, non-JS module files deprecated解决方式是,使用下面的新的写法:
// file:src/setupProxy.js const proxy = require("http-proxy-middleware"); module.exports = function (app) { app.use( // /api1是需要转发的请求(所有带有/api前缀的请求都会转发给5000) proxy.createProxyMiddleware("/api1", { target: "http://127.0.0.1:5000", // 配置转发目标地址(能返回数据的服务器地址) changeOrigin: true, // 控制服务器接收到的请求头中Host字段的值 /* changeOrigin 设置为 true 时,服务器收到的请求头中的 host 为:127.0.0.1:5000 changeOrigin 设置为 false 时,服务器收到的请求头中的 host 为:127.0.0.1:3000 changeOrigin 默认为 true ,但我们一般将 changeOrigin 值设为 true */ pathRewrite: { "^/api1": "" }, // 重写请求路径,去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置) }), proxy.createProxyMiddleware("/api2", { target: "http://127.0.0.1:5001", changeOrigin: true, pathRewrite: { "^/api2": "" }, }) ); };
无论使用哪种方式,都可以解决上文跨域的问题。
注意 无论使用哪种代理方式,一定要重新启动 React 才能生效!!!
-