cr的两个参数:initialState是初始状态;handlers是由一堆函数组成的对象,每个函数的名称对应着一个action的类型, 每个函数接受的参数与reducer一样,是action和当前状态,返回值会被当做新状态。默认情况就不用我们处理了。
cac接受的第一个参数是action的类型名称,后面参数是所有附带数据的属性名称。
好了,把代码规整一下。对现在小小的模拟双向绑定的功能来说,我们还不需要记录密码的状态,不过我们也先写上,后面会用到。
最好先写action。因为一般来说,只要你想好了你得应用有什么功能,action就可以写了,而且action不依赖其它东西。
src/actions/login.js:
INPUT_USERNAME INPUT_PASSWORD inputUsername INPUT_USERNAMEinputPassword INPUT_PASSWORDaction类型名称的常量现在都写到了action文件里,不过也许把所有这些常量放到一个单独的文件里比较好, 这样在es6语法的帮助下就可以避免重复了。
这里我们把所有的东西都导出了,action类型名称reducer会用到,action生成器组件会用到。
然后写reducer。当你想好应用的功能后,接下来就是要考虑背后的数据结构了。而reducer一写出来,数据结构就确定了。
src/reucers/login.js:
crINPUT_USERNAMEusernameINPUT_USERNAMEvaluevaluepasswordINPUT_PASSWORDvaluevalue对action文件的引用,路径里没有用../,这样写是因为actions是一个别名,它代表actions目录的绝对路径,这是webpack帮我们做的。 当然你也可以定义自己的别名,修改cfg/base.js就行,比如在resolve.alias对象里加一个自己的工具集:“utils:srcPath + '/utils.js'”。
rducer最终是要注册到store那里的,这个过程在src/storces/index.js里面已经写了, 可以看到里面的代码用的是../reducers这个文件(这是个目录,实际的文件是里面index.js), 所以我们也需要把新写的reducer注册到这里面去。修改src/reducers/index.js:
login reducers = { login }; modulereducers);在reducers/index里,所有的reducer也是通过combineReducers组合到一起的,只不过现在我们只有一个孤零零的子reducer:login。
终于,是时候回到组件上来了。src/containers/Login.js现在要修改成这样:
connect inputUsernameComponentevtpropsevtevtpropsevtdiv早上好,props inputUsernameHandler papsswordinputPasswordHandler stateusername: state.login.username, password: state.login.password mapStateToProps有几处变化:
首先,前面已经说过,要把组件连接到仓库,就要用connect。并且现在我们已经确定了仓库里login对应状态的数据接口, 那么mapStateToProps返回的内容也就确定了。login状态里的两个属性映射成了组件的属性, 所以用this.props.username就可以访问到仓库里的login.username。
然后两个input上都加上了change事件处理。当change事件被触发时,通过this.props.dispatch函数就可以通知仓库有动作发生了, 仓库此时就会调用所有的reducer来应对这个事件。
好了,到这里小小的双向绑定功能实现了试试吧。
在MVVM框架里只需要建立一个视图模型,用一对双大括号就能完成的事情,到react加redux里面为何如此大费周折?
其实我是专门在展示完整的redux+react开发流程。如果只是要单个页面上的这点功能,用事件处理来改变组件的state就行了。 那么redux为什么要引入这么个流程?我在开发中觉得有这么几个特点:从直观上看在视野不一样。还是跟MVVM比吧, MVVM框架的视野在于局部,而redux的视野在于全局。MVVM对一个controller对应一个模型,模型里的数据只能自己用, 模型之间通信需要其它的数据传递方式。redux(或者说是flux的模式)管理着一个大数据仓库, 任何时候都可以从这个仓库中取到一切细节的状态(有没有云的感觉?),当开发单页应用的时候,这一优势会特别明显。 从编程语言角度上看,redux+react方式充分利用了函数式编程的优势。redux(flux)强调单向数据流, 单向数据流就像生产流水线,原料被各个工序依次加工,最终成为产品,而在这个过程中要避免外界因素对各个阶段的原料产生影响, 否则就会出现非预期的产品(次品)。纯函数就像这个流水线中的工序,让数据处理的过程简单明了。 发现了吗?前面的代码中纯函数是主力。reducer很明显是纯函数。组件也是纯函数,注意,我们的组件并没有直接被状态控制, 而是有个connect的过程,状态是被映射成组件的属性的,对于组件来说,根本不知道状态为何物。 这样我们的组件、reducer都非常独立,非常容易测试,意义也非常直白。
吹嘘了这么多,靠目前这点简单的代码也不容易看出来。毕竟这些代码还没啥实际意义,作为一个现代的前端应用,连异步都没有。。。
那么下一节,我们就加点异步进来。
上一节 【0】预备——开始下一节 【2】 异步action和redux中间件