React本身只关注于界面,并不包含发送ajax的请求。
前端应用需要ajax请求与后端交互(json数据)。
react需要集成第三方ajax库或自己封装。
常用ajax库
1.jQuery,比较重,如果需要可以引用,但是不建议使用。因为jquery的思想是在操作DOM,而React尽量让我们 不要去操作DOM。
2.axios,轻量级,提倡使用
1)axios是对Xml Request对象的ajax的封装
2)使用promise,返回的是promise对象
3)可在浏览器端和node服务器端运行
我们后端的启动端口是8000,前端是3000
安装 axios
npm install axios
可以看到axios已经在依赖中了
App.js使用axios
- 引入axios:import axios from 'axios' ;
- 声明state,里面有一个变量data
- componentDidMount 生命周期(挂载完毕)
- axios.get,get请求方式,参数是请求后断的URL。axios是一个Promise对象,then中是请求成功。还没有写服务端代码也就是后端借口,我们先用❓代替
- 请求成功,setState去修改值
import React from 'react' ;
import './App.css' ;
import axios from 'axios' ;
class App extends React . Component {
state = {
data : ''
}
componentDidMount() {
axios.get('?')
.then( res => {
this.setState({
data : res.data.data
}, () => console .log( this.state.data))
})
.catch( err => console .log( "Couldn't fetch data. Error: " + err))
}
render() {
return (
<div className = 'ArticleContainer'>
{this.state.data}
</div>
)
}
}
export default App;
后端接口
我们axios.get中请求的是后端地址。
后端我用的是Django
刚才axios.get的路由可以填入了 http://localhost:8000/my_view/
在没有代理之前我们会发现发生了跨域问题
思考
因为跨域问题ajax是没法发送请求,还是请求后没有数据?
我们在后端打印,可以发现打印了。
代理
同源地址访问/跨域
会出现跨域问题,我们前端(client)的端口是3000,我们的后端(server)端口是8000。从客户端发送的ajax请求,去请求服务端的8000。这个请求ajax是允许了,但是服务端的响应回到客户端时被拒绝了。
而代理是一个中间人,也是开在3000端口上的,3000端口上启动着脚手架也开着一台微小的服务器。3000发送请求给3000会被允许,3000端口上的中间人再发送请求给8000端口。那么为什么这个中间人就可以发送请求给8000端口呢?因为它上面没有ajax引擎。
怎么配置代理呢?
方法一
在package.json中添加 proxy,这个代理地址只写到端口号即可,不需要后面的具体路由
修改过package.json,需要将服务停掉再重启才会有效
我们axios.get()中的请求地址中端口还是8000,需要将其改为3000.也就是我们上面所说的
我们再试验一下。把axios.get中的请求地址改为http://localhost:3000/index.html 可以发现它请求成功。它请求的并不是服务端的,而是脚手架、也就是3000端口的public文件夹下的index.html。当3000端口下能找到就返回,如果没有才会去请求8000端口。当二者都没有才会返回404.
方法二
我们上面的方法只适用于 对应一个后端的项目,当我们同时需要请求多个后端(多个端口)就不可以了。
首先,去掉package.json中的proxy
在src文件夹下新建setupProxy.js(名称不能更改,自动找到这个文件)。而且这里面的语法不能使用Es6,需要common js的语法。
// 因为是cjs 需要require ,不能使用import
// 在初始化脚手架的时候http-proxy-middleware已经下载了
const proxy = require('http-proxy-middleware')
// 暴露一个对象
module.exports = function(app){
//调用app的use方法
app.use(
proxy('/api1',{ // 遇到/api1前缀的请求,就会触发该代理配置
// 转发给谁
target:'http://localhost:8000',
// 让服务器知道从哪发出的 控制服务器收到的请求头的Host字段的值
changeOrigin:true,
// 把api1 替换成空格。去除请求前缀,保证交给后台服务器是正常请求地址
pathRewrite:{'^/api1':''}
}),
// 添加多个
proxy('/api2',{
target:'http://localhost:8001',
changeOrigin:true,
pathRewrite:{'^/api2':''}
})
)
}
我们请求的接口也需要添加api1
componentDidMount() {
axios.get('http://localhost:3000/api1/my_view/')
.then( res => {
})
.catch( err => console .log( "Couldn't fetch data. Error: " + err))
}