继续前面一篇的话题,开始学习react,redux。
react:
1、概括来说,它就是将页面进行组件化,这样就可以对这些组件进行复用。(中文学习网址: http://reactjs.cn/react/docs/tutorial.html )
2、JSX:在react中会出现以JSX结尾的文件。这种文件中是 React 独有的 JSX 语法,跟 JavaScript 不兼容,我们可以理解为用JSX结尾的文件中,可以直接使用html来进行编码就可以了。
redux: 用它自己的话说:Redux 是 JavaScript 状态容器,提供可预测化的状态管理(http://camsong.github.io/redux-in-chinese/index.html)。它不但和可以和react来配合使用,也能和其他的界面库进行配合使用。当前已有的react-redux,就是react和redux的桥梁。
3、首先记住一个图:react和redux的工作图(从网上copy的):
1)这里的组件,我们先简单的理解为我们使用react来实现的可视化的某个按钮或者图标。用户第一眼看到的就是组件和组件上展示的数据,这个数据的值就存在state中。现在我们先假设这个组件是一个按钮,上面有文字。
2)action:动作,可以理解为组件可以响应的动作。比如说这个按钮可以点击,那么这个action就需要定义一个点击的动作。
3)reducer:可以理解为应对action这个动作,将state中的数据进行修改的行为。state是不可以直接进行修改的,必须通过触发action,然后reducer再根据action将数据更新进state中。
4)state:这个东西就是纯纯的数据了,它通过组件进行展现。当reducer进行更新state之后,组件会自动更新展示的数据。
下面我们来举个栗子,用来详细说明这些东西。可能会写到哪说到哪,没怎么写博客,请见谅。
图如下,就是一个加法的按钮(bootstrap我们先不管,理解先再说) :
先看下总的文件目录:
├── actions 这里包含的文件,都是actions的集合
│ ├── ActionCounter.jsx
│ ├── ActionCounter1.jsx
│ └── HomeActions.js
├── components 这里的文件,都是组件
│ ├── ComponentsCounter.js
│ ├── ComponentsCounter1.js
│ └── Home.js
├── constants 这里的文件,都是将actions的操作类型统一定义
│ └── ActionTypes.js
├── containers 将app的入口设置在这里。可以注册多个组件
│ ├── App.js
│ ├── hello.jsx
│ └── stock.jsx
├── index.js 入口js
├── reducers action中定义的动作,在这里都有对应的改变state的函数
│ ├── ReducersCounter.js
│ ├── ReducersCounter1.js
│ ├── Sample.js
│ └── index.js
├── store 设置state的初始化
│ └── configureStore.js
└── utils 一些杂类,包含中间件
├── devTools.js
└── logMiddleWare.js
按照上面的目录结构,同时结合工作图,开始开发那么一个简单的东西。
1、定义一个action,该action就是相应组件求和按钮的动作的。
GET_SUM : 这种定义应该统一放在一个文件。
return的内容,这个返回一个action,其中type是必须的,填为该action的类型,其他是自己定义的,不提倡写入太多的数据。其中action的书写规范地址: https://github.com/acdlite/flux-standard-action
2、定义一个组件,该组件就是一个表单。就包括三个输入框和一个点击按钮,当点击的时候就得出和。
submitHandler :用以响应点击事件。调用action的方法可以如图中所示,选择其中一种。
export default connect(state => state.Counter)(Counter); 这一句比较关键,指的是,使用reducer中的Counter来对action事件进行响应。
3、定义一个reducer,用以给action来填充数据,在reducer中不应该做除了填充数据之外的其他动作。
如果后面再出现减法,可以直接在这个函数中对类型进行区分然后进行操作。
4、最后将组建注册到app中:
需要注意的是: Provider 中只能包含一个组件,如果有多个组建,需要多个组件一起,如:
还有一点关于store的,就是在整个工程中,这个是唯一的,如果有多个reducer,那么其实也是用combineReducers函数,将这些reducer整合在一起,形成一个类似树一样的数据结构:
5、关于store目录,这里的代码比较少,但是包含了中间件的内容。
applyMiddleware函数: 该函数可以将中间件组合到流程图中来,没有使用该函数时,其数据流如下:
组件=>action=>reducers=>state=>组件。state就是我们程序中自行给我们维护的数据。如果我们想在这个数据流中插入一个功能,比如想进行每次reducers执行之前,打印一下state的内容,也就是说数据流要变成这样: 组件=>action=>其他=>其他…..=>reducers=>state=>组件,如果不使用applyMiddleware是不可能的。如下我们写一个打印日志的中间件:
const returnValue = next(action);
这一行的returnValue是任何中间件都必须返回的。表示让 applyMiddleware执行完本中间件之后,下一个应该执行的action是哪个。
6、关于thunkMiddleware,这个函数解释起来比较拗口,在官网上说它是异步action。其实就本菜理解,跟异步相关的都要么涉及多线程或者至少来个IO复用啥的,因此对它迷惑了好久。其实可以完全不管它叫什么,只要简单的理解为,其实他就提供了一个为延迟再决定调用哪个action的解决方案。我们再在刚刚的栗子上改改来看。把刚才的加和变成那么一个屌丝的东西,用以确认其所说的所谓异步到底是个什么鬼,同时也可以顺便看看内部的state的状态变化:
该按钮点击之后,接受后台返回的json数据,随便挑一个字段来进行展示,变成下面这个:
1)既然要跟后台服务进行交互,我就随便抄了个后面服务的例子,返回一个jison数据(当然在实际应用中这个数据的或者不应该那么简单的,暂时先不管): {id:100,name:”chenyinjing”},后台服务例子:
先将其跑起来。
2)再修改原本的action中的定义。由于有网络交互我们需要定义三个操作的类型,一个用以展示在组件上让用户知道当前在进行交互,一个用以在网络响应失败的时候应该提示用户的数据,还有一个用以定义网络成功后的需要进行的action.
这里会发现定义了四个函数,那么刚刚说了,只需要三个action剩下的那个是什么鬼?这个其实就是之前说的,用以提供延迟调用action的函数的入口。首先先执行POSTS_REQUEST动作,使得当前组件展示目前正在请求后台中,然后再使用fetch进行HTTP请求。最后将返回的json数据返回给展示组件。在这里没有进行异常检测。
3)组件的实现就比较简单了。再抄抄:
4)最后我们运行一下,看下state的状态变化:
估计很多人和我一样有疑惑,就是action里面定义的返回的数据中,和reducer返回的数据之间的关系,看这里,估计大家都明白了,action中定义的是,组件的动作会产生哪些数据,而reducer返回的数据返回的是,这个action进行一系列操作之后,可能会产生一些数据结果,而这些结果就是reducer数据定义返回的。
7、关于redux-router:原本想看看这里的,但是因为官方的版本这里变化非常频繁,所以就没有看。想着后面点看看能不能出个稳定版。
最后,关于redux写完了,都是非常简单东西,希望大神路过。后面会继续学习关于bootstrap的东西才行。