前言
本项目主要观察浏览器向后台发出请求后的三种结果的状态,使用react-redux编写项目,react渲染视图部分,redux存储Success请求成功、Fail请求失败、Loading加载中等三种状态以及相关逻辑行为。
一、项目框架
基本流程图:
(流程图照片像素太低,很久以前画的了,没有备份具体以下面叙述为主)
因为前面学过了模块化编程
React复习(5):模块化项目-待办事项表
对于一个项目,模块化编程可以快速定位到要改变的文件,所以本项目也采用模块化编程。设置list功能区,具体框架如下:
与(5)项目代办事项一样的思路,reducer中编写三种状态对应的逻辑,action中编写三种状态下触发的函数,action会作为参数传递到reducer中,最后都导入到index中对外暴露。
二、List功能区
1.action.js
因为要和服务器进行交互,所以我们要考虑在什么时候发起axios请求,因为reducer中会存储我们定义的逻辑及状态,所以我们这里我们需要获得后台传来的数据,所以我们在编写action时进行axios请求,将请求来的数据进行分情况处理(上篇博客最后请求成功后我们得到结果数据由data.data表示 博客地址:React复习(6):服务器相关(项目前篇))。
请求的结果三种:请求成功、失败、加载中。分别定义三种处理函数,分别调用,然后返回,最后暴露export。代码如下:
// 三个构造函数
import axios from 'axios'
import {Loading,Success,Fail} from './actionType'
//发起请求函数
const axiosData=function(){
axiosLoading()
axios.get("/s").then((data)=>{
var res=data.data
axiosSuccess(res)
}).catch(()=>{
axiosFail()
})
}
// 请求成功
const axiosSuccess=function(data){
return {
type:Success,
data:{
status:Success,
list:[
data
]
}
}
}
// 请求失败
const axiosFail=function() {
return {
type:Fail,
data:{
status:Fail,
list:[]
}
}
}
// 加载中
const axiosLoading=function(){
return {
type:Loading,
data:{
status:Loading,
list:[]
}
}
}
export default axiosData
2.reducer.js
这里我们定义reducer函数,它是我们更改状态的逻辑,传入的参数是我们上一步编写的action,action返回的是经过处理后的数据:如果请求成功就将data.data发送过来,否则返回对应状态和[]。
(这里我们的data数据分两个部分status状态和list数据,reducer初始化时我们表示过)
对于action的数据,我们取里面的data覆盖原有状态state,代码如下:
//三种状态判断:请求成功、请求失败、加载中
import {Loading,Success,Fail} from './actionType'
const reducer=function(state={
list:[],
status:""
},action) {
switch(action.type){
case Loading:{
return {
...state,
...action.data
}
}
case Success:{
return {
...state,
...action.data
}
}
case Fail:{
return {
...state,
...action.data
}
}
default:{
return state
}
}
}
export default reducer
3.index.js
对外接口文件
代码如下;
import List from './views/List'
import reducer from './reducer'
export {List,reducer}
4.List组件
简单组件框架,使用connect对外导出
import React,{Component} from 'react'
import {connect} from 'react-redux'
class List extends Component{
constructor(props){
super(props)
}
render(){
return (
<div>List</div>
)
}
}
export default connect()(List)
5.actionType
为了方便处理而提取出的变量
const Loading="Loading"
const Fail="Fail"
const Success="Success"
export {Loading,Success,Fail}
三、store创建及中间件使用
中间件了解不深,但是固定模式使用,有待学习,具体代码如下:
import {reducer} from './list/index'
import {createStore,compose,applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
const middleware=[thunk];//填放中间件的位置
const storeEhances=compose(
applyMiddleware(...middleware),
(window && window.devToolsExtension)?window.devToolsExtension():(f)=>f
)
const store =createStore(reducer,{},storeEhances)
export default store
因为我们使用了thunk中间件,而这个中间件要求我们的action返回的是一个函数,传递的参数为dispatch,所以action代码如下:
// 三个构造函数
import axios from 'axios'
import {Loading,Success,Fail} from './actionType'
//发起请求函数
const axiosData=function(){
return function (dispatch) {
dispatch(axiosLoading())
axios.get("/s").then((data)=>{
var res=data.data
dispatch(axiosSuccess(res))
}).catch(()=>{
dispatch(axiosFail())
})
}
}
// 请求成功
const axiosSuccess=function(data){
return {
type:Success,
data:{
status:Success,
list:[
data
]
}
}
}
// 请求失败
const axiosFail=function() {
return {
type:Fail,
data:{
status:Fail,
list:[]
}
}
}
// 加载中
const axiosLoading=function(){
return {
type:Loading,
data:{
status:Loading,
list:[]
}
}
}
export default axiosData
四、数据的渲染
React复习(6):服务器相关(项目前篇)中我们是在react视图中直接发起的axios请求,这里我们发起请求的地方是在action文件下的axiosData函数里,所以我们通过定义mapDispatchToProps函数传入connect的方式导入axiosData方法,然后在react组件的componentDidMount生命周期方法下调用。
上一步是在向服务器请求数据,我们知道connect方法是帮助我们获取我们当前组件想要获得的状态和方法,我们需要请求数据,更改同步到状态中并渲染到视图中,所以我们不仅需要定义mapDispatchToProps,还要定义mapSateToProps去渲染我们的视图
(不想说话,因为忘了改了服务器后要重新node一遍,孩子找了好久的bug,骂骂咧咧反复deBug)
控制台结果:
先是Loading,后面便是Success和我们的数据
组件代码如下:
import React,{Component} from 'react'
import {connect} from 'react-redux'
import {axiosData} from '../action'
class List extends Component{
constructor(props){
super(props)
}
render(){
const {status,list} =this.props
console.log(this.props)
return (
<div>
<p>{status}</p>
<ul>
{list.map((item,index)=>{
return <li key={index}>Name:{item.name}</li>
})}
</ul>
</div>
)
}
componentDidMount(){
this.props.getData()
}
}
const mapStateToProps=function(state){
console.log(state)
return {
status:state.status,
list:state.list
}
}
const mapDispatchToProps=function(dispatch){
return{
getData(){
dispatch(axiosData())
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(List)
最终渲染效果如下:
对比我们服务器传来的数据:
const express =require('express')
const app=express();
app.get('/s',(req,res)=>{
var arr=[{
name:"小明",
},{
name:"123"
}]
res.send(arr)
})
app.listen(4000)
五、console.log(“Fnial”)
需要注意:
1、服务器改了要重新运行
2、proxy代理服务器这里就很神奇,一句话的事情,可以实现3000端口的项目请求4000端口的数据
3、敲代码要带脑子
项目文件(文件使用要记得npm install
下载相关依赖包):
链接:https://pan.baidu.com/s/1sEgSynaJWyrEhppam-rWSg
提取码:fbrw