这一篇主要写了React脚手架使用,axios,代理配置,消息订阅和发布,以及fetch
React脚手架
React脚手架是一个工具,能够帮我们快速的生成项目的工程化结构!
脚手架安装
全局安装: npm i -g create-react-app
切换到想创项目的目录,使用命令: create-react-app 文件名
项目结构
hello-react
├─ .git // 自动创建本地仓库
├─ package.json // 相关配置文件
├─ public // 公共资源
│ ├─ favicon.ico // 浏览器顶部的icon图标
│ ├─ index.html // 应用的 index.html入口
│ ├─ logo192.png // logo
│ ├─ manifest.json // 应用加壳的配置文件
│ └─ robots.txt // 爬虫给协议文件
├─ src // 源码文件夹
│ ├─ App.css // App组件的样式
│ ├─ App.js // App组件
│ ├─ App.test.js // 用于给APP做测试
│ ├─ index.css // 样式
│ ├─ index.js // 入口文件
│ ├─ logo.svg // logo图
│ ├─ reportWebVitals.js // 页面性能分析文件
│ └─ setupTests.js // 组件单元测试文件
└─ package-lock.json
publuc下index.html代码解读
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<!-- %PUBLIC_URL%代表public文件夹的路径 -->
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- 开启理想视口,用于做移动端网页的适配 -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- 用于配置浏览器页签+地址栏的颜色(仅支持安卓手机浏览器) -->
<meta name="theme-color" content="red" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<!-- 用于指定网页添加到手机主屏幕后的图标 -->
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!-- 应用加壳时的配置文件 -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<!-- 若不支持js则展示标签中的内容 -->
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
React使用axios发送客户端请求
React 本身只关注于页面,并不包含发送Ajax请求的代码,所以一般都是集成第三方的包,比较推荐的就是axios
axios安装
import axios from 'axios'
使用
import axios from 'axios'
axios.get('http://192.168.189.1:3000/api1/search/users').then(
response => {
// 成功的处理
},
error => {
// 失败的处理
}
)
脚手架中配置代理
在我们开发中经常会遇到跨域的问题,跨域源于浏览器的同源策略。所谓同源(即指在同一个域)就是两个页面具有相同的协议,主机和端口号, 当一个请求URL的协议、域名、端口三者之间任意一个与当前页面URL不同即为跨域,下面我们就用前端的方式来解决一下跨域。
全局代理
第一种方法,我把它叫做全局代理,因为它直接将代理配置在了配置文件 package.json 中
"proxy":"http://localhost:5000" // 要请求的地址
这样配置代理时,首先会在原请求地址上访问,如果访问不到文件,就会转发到这里配置的地址上去请求
优点:配置简单,前端请求资源可以不加任何前缀,缺点:不能配置多个代理
工作方式:当请求了接口首先会在本地找你所请求的资源,如果没有会通过代理像5000端口发起请求,数据返回之后再由代理发给客户端,以此来解决跨域,但是这种方式也存在一些问题:
1. 当本地又访问的文件的话,就不会在向服务器发起请求
2. 因为这种方式采用的是全局配置的关系,导致只能转发到一个地址,不能配置多个代理
单独配置(可配置多个代理)
首先 我们需要在React脚手架 src 目录下,创建代理配置文件 setupProxy.js,然后在setupProxy.js里配置代理,这样就可以配置多个代理了
注意:*这个文件只能叫这个名字,脚手架在启动的时候,会自动执行这些文件*
优点:可以配置多个代理,可以灵活的控制请求是否走代理
缺点:配置繁琐,前端请求资源时必须加前缀
const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = function (app) {
app.use(
createProxyMiddleware('/api1', {// 遇见 /api 前缀的请求,就会触发该代理配置
target: 'http://localhost:5000',// 请求转发给谁
changeOrigin: true,//控制服务器收到的响应头中Host字段的值
pathRewrite: {
'^/api1': ''//重新请求路径
}
}),
createProxyMiddleware('/api2', {// 遇见 /api 前缀的请求,就会触发该代理配置
target: 'http://localhost:5001',// 请求转发给谁
changeOrigin: true,//控制服务器收到的响应头中Host字段的值
pathRewrite: {
'^/api2': ''//重新请求路径
}
}),
)
}
消息订阅发布
之前由于还没有学到兄弟组件传值,所写的案例都是通过子组件传递给父组件,父组件再传递给子组件,略嫌麻烦,下面学习了消息订阅发布,我们就可以实现兄弟组件之间直接通信!
pubsub-js安装
npm install pubsub-js --save
使用
// 引入
import PubSub from 'pubsub-js'
订阅消息
我们通过subscribe来订阅消息,它接收两个参数,第一个参数是消息的名称,第二个是消息成功的回调,回调中也接受两个参数,一个是message,一个是接收到的数据(谁接收消息谁就订阅消息)
// 写在componentDidMount钩子中,页面已挂载完成就订阅
componentDidMount(){
this.token = PubSub.subscribe('search',(msg,data)=>{
console.log(msg,data);
})
}
发布消息
我们采用 publish 来发布消息,用法如下
// 比如再点搜索后进行消息发布
clickSearch = ()=>{
PubSub.publish('search',{name:'tom',age:18})
}
取消订阅
// 页面卸载时取消订阅
// 在页面要卸载时,在 componentWillUnmount() 钩子里,通过 unsubscribe 来取消指定的订阅
componentWillUnmount(){
PubSub.unsubscribe(this.token)
}
扩展 -- Fetch
fetch也是一种发送请求的方式,它是在xhr之外的一种,我们平常用的Jquery和axios都是封装xhr的第三方库,而fetch是官方自带的,同时它也采用的是Promise的方式,更好的关注分离(比如请求接口,成功了并不是先返回数据,而是告诉你接口是好的可以访问,想要拿到接口返回的数据还需要进行进一步的操作)
fetch('http://xxx')
.then(response => response.json())
.then(json => console.log(json))
.catch(err => console.log('Request Failed', err));
和axios不同的是,fetch关注分离,它在第一次请求时,不会直接返回数据,会先返回联系服务器的状态,在第二步中才能够获取到数据我们需要在第一次then中返回response.json()因为这个是包含数据的 promise对象,再调用一次then方法即可得到数据,我们可以利用 async 和 await 配合使用,来简化代码
async function getJSON() {
let url = 'https://xxx';
try {
let response = await fetch(url);
return await reasponse.json();
} catch (error) {
console.log('Request Failed', error);
}
}
小结
下一篇就开始学习React中的路由了!Go、Go、Go!