吐槽
Facebook全家桶真是够了,从react到react-router再到redux,看的我成就感满满啊,然后才告诉我,这一切都还只是个开始。好咯。用别人框架的人我还能说什么。
对redux的理解(数据流分析)
之前用学过的react和react-router写了个单页面应用,但写完后总感觉还欠缺点什么,怎么说呢,就是感觉在数据流的控制上被框架约束的厉害,很不自由,比如兄弟组件间的通信就很不方便。然后才了解到,还需要一个能全局控制整个应用数据流的框架,就是框架的框架,然后就选择了redux,因为它在github上面星星比较多。
根据我的理解下面说一下redux的思想:
redux由三个部分组成,即store,reducer以及action,直观一点,你可以把store理解为数据库,reducer是事件处理函数,action是触发事件。为什么可以这么理解呢,因为整个redux的大致逻辑是这样的:
1 dispatch(action),即触发action,(事件发生)
2 reducer根据当前所触发action执行相对应的函数,更新state,(执行事件处理函数,更新数据库数据)
3 store的state会为应用所获取,像数据库一样
当然可能并不是那么契合,但大致的可以这么理解。现在我们再仔细的看一看redux的数据流。
1 dispatch的action会被reducer捕获到,其实是action先被传送至store,再由store交付给reducer的,因为dispatch是store的方法,action通过回调到达的store,而之前我们在创建store的时候使用了这样的声明 var store = createStore(reducer),使得store与reducer建立了某种联系,自然的,reducer能够接收到触发的action。
2 上面是redux内部数据流的实现,但是redux与应用之间的数据流动是怎么建立起来的呢?因为一般来说,是由应用的视图触发action,然后redux的reducer根据接收到的action执行相应的处理函数更新store的state,而state又是作为数据来源与应用绑定的,所以store的state一更新,应用视图也会同步刷新。所以这里的问题是,应用是如何获得dispatch action的能力已经来自store的数据的呢?这个就需要借助react-redux的Provider以及connect组件了。
通过Provider组件为应用组件再加一层外壳,并传入整个应用的store。
connect组件负责链接store与应用。其中select函数会接收到来自store的state,在这里可以对state进行相应的预处理再返回应用所需state,state会连同store的dispatch方法以属性方式传入App组件即应用组件。
todo项目,说明整个项目的核心思想
redux的数据流思想大致如此,但这只是我自己的理解,可能会有不少的纰漏。
看了redux官方文档之后,照着葫芦画瓢也实现了一个todo小应用。
整个应用的编写思路其实不外乎上面所谈及的那些。
但是需要注意的是,上面截图中的第一条todo其实是通过异步添加上去的,然而dispatch只能触发同步的action,即传递普通的action对象,因为这样我们的action才能被reducer所接收到并触发相对应的处理函数。所以,如果需要触发异步的action的话,常规的方法是不行了的,我们需要使用点小技巧。这里又涉及到redux中间件(middleware)的概念了。简单介绍下,所谓中间件,就是在action被触发以及还没被reducer接收到之间这段时间所执行的一段函数,其内部封装有dispatch方法。中间件的存在是dispatch扩展的唯一标准方式。
我们想要使用中间件的话,需要借助applyMiddleware方法,它能够使中间件与store建立某种联系,使得store的dispatch和getState方法传入中间件。
说回我们之前所说的异步action,异步请求的实现我们可以借助于redux-thunk中间件,这个中间件会去拦截异步action,因为一般情况下异步action是action创建函数所返回的一个函数,所以redux-thunk中间件会替我们去执行这个函数。执行的最后,一般会dispatch普通的action对象,reducer捕获到此action对象,做出相应。
这是我们的异步action创建函数,会返回一个异步函数
//异步action export function asyncAction(){ return function(dispatch, getState){ setTimeout(function(){ dispatch(addTodo("2秒钟过去啦!你还没添加新的任务,我来帮你添加一个吧!")) },2000) } };
然后我们dispatch它
dispatch(asyncAction());
因为返回的是异步action对象(函数),会被redux-thunk拦截并执行,执行的最后dispatch一个普通的action事件,成功添加一条todo。
完整的代码在这里 https://github.com/JerelLin/redux-todo
结尾
睡觉