本文是继上一篇《React进阶漫谈》后的第二篇文章。本文主要分析redux的思想和应用,也参考了网上的大量资料,不过代码也是自己尝试和实践过的,在此分享,供大家一起学习(最后地址:个人blog/segmentFault)注意:本文中所有的示例代码都被合成了一个小demo放在了这里。如果您觉得这个demo对您的学习有一点帮助,请给个star支持。redux介绍本文默认大家对react和flux架构有一定的了解,使用过或者了解过redux,所以不会从最基础的开始,直接对redux进行总结。如果你从未使用过redux,最好先看看这里。要理解redux,首先要总结一下redux的一些设计原则:在Redux中,只用一个单一的对象树结构来存储整个应用的状态,也就是整个应用都会用到的数据,我们称之为store(存储).除了存储的数据,store还可以存储整个应用的状态(包括router的状态,后面会介绍)。因此,通过Store,可以实现整个应用的即时保存功能(创建快照)。另外,这种设计也为服务端渲染提供了可能。状态为只读,符合flux的设计理念。我们不能在components中改变store的状态(其实redux会根据reducer生成store),只能通过dispatch触发action迭代当前state。这里我们也没有直接修改应用的状态,而是返回了一个全新的状态。状态修改由纯函数组成。Redux中的reducer的原型会像下面这样,你可以把它看作是前一个状态+action=新状态的公式:(previousState,action)=>newState对于每个reducer它们都是纯函数,也就是说他们没有任何副作用。这种设计的好处不仅仅在于使用reducer修改状态变得简单,纯可测试。此外,redux可以保存每个返回状态,从而轻松生成时间旅行并跟踪每个动作引起的变化结果。如果我们在react中使用redux,那么我们同时需要react-redux和redux。redux架构和源码分析这部分主要说一下自己的理解。可能有点抽象,也可能不是完全正确,可以直接跳过。createStoredux中的核心方法是createStore。React的核心功能都在createStore及其最终生成的store中涵盖了。createStore方法本身支持三个参数:reducer、initialState和enhancer。Enhancer可以用作增强的包装函数。我们不是很常用。这个函数内部维护了一个currentState,这个currentState可以通过getState函数(内置)返回。另外,它实际上实现了一种发布-订阅的模式,通过store.subscribe来订阅事件。这项工作是由react-redux隐式完成的,这是在有dispatch更新整个状态树时触发所有的监听器。另外,内置的dispatch函数在经过一系列的检查后触发reducer,然后改变state,然后依次调用listener完成整个statetree的更新。middleWare用过redux的朋友其实对redux-thunk这样的中间件并不陌生。事实上,在很多情况下,它是不可或缺的。Redux对中间件也有很好的支持。我觉得这个概念类似于nodejs的中间件机制。有些是类似的:action依次经过每个middleWare再传递给下一个,每个middleWare还可以进行其他的操作比如中断或者改变action,直到最终的处理功能交给reducer。redux的applyMiddleware函数非常精炼:exportdefaultfunctionapplyMiddleware(...middlewares){return(createStore)=>(reducer,preloadedState,enhancer)=>{varstore=createStore(reducer,preloadedState,enhancer)vardispatch=店铺。dispatchvarchain=[]varmiddlewareAPI={getState:store.getState,dispatch:(action)=>dispatch(action)//注意这里的dispatch不是原来的store.dispatch,而是实际变了}chain=middlewares.map(middleware=>middleware(middlewareAPI))dispatch=compose(...chain)(store.dispatch)return{...store,dispatch}}}核心是dispatch=compose(...chain)(store.dispatch),这句话是对每个中间件的链式调用,其中compose的源码:exportdefaultfunctioncompose(...funcs){if(funcs.length===0){returnarg=>arg}if(funcs.length===1){returnfuncs[0]}constlast=funcs[funcs.长度-1]constrest=funcs。slice(0,-1)return(...args)=>rest.reduceRight((composed,f)=>f(composed),last(...args))}将上一个函数的执行结果调用到下一个函数。其实写一个中间件的过程也很简单。比如redux-trunk其实有这样的内容:,getState,extraArgument);}返回下一个(动作);};}constthunk=createThunkMiddleware();thunk.withExtraArgument=createThunkMiddleware;exportdefaultthunk;redux和routing当然,我们首先声明react工具集的react-router不一定非要和redux一起使用,而是redux还有一个react-router-redux可以配合react-router和redux一起使用,效果很好。因为我们这部分没有介绍如何使用react-router,所以react-router的使用请参考中文文档。react-router的特性允许开发者通过JSX标签来声明路由,这使得我们的路由写起来非常友好,声明式路由的表达能力是比较强的。嵌套路由和路由匹配:参数可以在指定路径中传递:
