03-React网络通信(Axios, PubSubJs, Fetch)
创建项目
create-react-app react_axios
添加axios依赖
yarn add axios
配置代理
在package.json中配置
"proxy": "http://localhost:8080"
使用时需要将访问端口改为自身端口
import React, {Component} from 'react'; import axios from "axios"; class App extends Component { queryData = () => { # 访问3000端口, 然后通过代理,访问8080 axios.get("http://localhost:3000/students").then( response=> { console.log(response) }, error => { console.log(error) } ) } render() { return ( <div> <button onClick={this.queryData}>获取数据</button> </div> ); } } export default App;
但是这样会存在一个问题, 那就是访问自身3000存在的资源就不会转发给8080
修改为
其实就是public/index.html
多代理配置
在src下新建setupProxy.js, 记得删除package.json中的proxy
// 需要写 CJS语法 // 导入代理中间件 const {createProxyMiddleware} = require('http-proxy-middleware') module.exports = function (app) { app.use( createProxyMiddleware('/test', { target: 'http://localhost:8080', changeOrigin: true, pathRewrite:{ '^/test':'' } }), createProxyMiddleware('/dev', { target: 'http://localhost:8081', changeOrigin: true, pathRewrite:{ '^/dev':'' } }) ) }
使用时添加前缀
这样就可以转发多个网络请求了, 通过前缀区分,要代理到哪里
连续解构赋值
const key = { value:{ title:'123' } } # 连续解构赋值 const {value:{title}} = key # 只能使用title, 而不能使用value
解构赋值后重命名
const key = { value:{ title:'123' } } # 连续解构赋值 将title重命名为标题 const {value:{title:bt}} = key
消息订阅与发布(PubSubJs)
添加依赖
yarn add pubsub-js
使用
App.js
import React, {Component} from 'react'; import axios from "axios"; import Pub from "./components/pub/pub"; import Sub from "./components/sub/sub"; class App extends Component { render() { return ( <div> <Pub/> <Sub/> </div> ); } } export default App;
Pub.js
import React, {Component} from 'react'; import PubSub from "pubsub-js"; class Pub extends Component { render() { return ( <div> <button onClick={this.send}>发送消息</button> </div> ); } send = () => { const items = ['a','b','c'] PubSub.publish('pub',items) console.log("发送数据") } } export default Pub;
Sub.js
import React, {Component} from 'react'; import PubSub from 'pubsub-js' class Sub extends Component { state = { items: ['html', 'js', 'css'] } componentDidMount = () => { // 订阅消息 console.log("订阅消息") this.token = PubSub.subscribe('pub', (_, items) => { console.log("sub接收到数据", items); this.setState({items}) }) } componentWillUnmount() { // 在组件卸载时取消订阅 PubSub.unsubscribe(this.token) } render() { const {items} = this.state return ( <div> <ul> { items.map(item => { return <li key={item}>{item}</li> }) } </ul> </div> ); } } export default Sub;
执行结果
效果没有问题, 但是消息被订阅了两次
componentDidMount函数被连续执行两次的问题
因为我在订阅之后发现这个生命周期被连续执行两次,导致一下订阅了两次,出现问题
解决办法
把index.js中的React.StrictMode删除即可
删除后发现剩余此一次一次了
扩展知识: Fetch
文档
https://github.github.io/fetch/
特点
- fetch: 原生函数,不再使用XmlHttpRequest对象提交ajax请求
- 老版本浏览器可能不支持
Get请求
fetch('http://localhost:3000/test/students').then( response => { console.log("联系服务器成功",response) return response.json() } ).then( response => { console.log("获取数据成功",response) } ).catch( error => { console.log("失败",error) } )
Post请求
const items = ['a','b','c'] fetch('http://localhost:3000/test/students',{ method:'POST', body:JSON.stringify(items) }).then( response => { console.log("联系服务器成功",response) return response.json() } ).then( response => { console.log("获取数据成功",response) } ).catch( error => { console.log("失败",error) } )
优化写法
try { const response = await fetch('http://localhost:3000/test/students', { method: 'POST', body: JSON.stringify(items) }) const data = await response.json() console.log(data) } catch (e) { console.log("失败了",e) }
记得在外部函数写async