上一篇:react、react-router、redux可能是最好的小实践1添加reduxReact实现组件间数据循环。更准确地说,这叫做“单向数据流”——数据从一个方向从父组件流向子组件。由于这个特性,在没有父子关系的两个组件之间交换数据变得不那么明显。这里Redux就派上用场了。Redux通过将应用程序的所有状态存储在一个称为“存储”的位置来提供解决方案。然后组件可以将状态更改“分发”到商店,而不是直接与其他组件通信。所有组件都应该知道可以“订阅”商店的状态变化。如下图所示:说完原理,我们开始添加代码。我们先来看一个小例子。在开始之前,您需要使用Redux.createStore()创建一个存储,然后将所有的reducer作为参数传入。让我们来看看这个只传递一个reducer的小例子:varuserReducer=function(state,action){if(state===undefined){state=[];}if(action.type==='ADD_USER'){state.push(action.user);}returnstate;}varstore=Redux.createStore(userReducer);store.dispatch({type:'ADD_USER',user:{name:'xiaoming'}});上面的程序做了什么:这个store只是由一个reducer创建的。这个reducer用一个空数组初始化它的状态。*新的用户对象用于调度的动作。reducer将新用户对象附加到状态并将其返回以更新存储。*在这个例子中,reducer实际上被调用了两次——一次是在创建store时,一次是在调度action之后。当store被创建时,Redux立即调用所有reducer,并使用它们的返回值作为初始状态。对reducer的第一次调用为状态传递了一个undefined。经过reducer内部的代码处理后,返回一个空数组作为store的状态作为开始。在分派每个动作后调用所有减速器。因为reducer返回的状态将成为存储在store中的新状态,Redux总是期望所有的reducer都返回一个状态。在此示例中,reducer的第二次调用发生在分派之后。请记住,分派的操作描述了更改状态的意图,并且通常携带用于更新状态的数据。这一次,Redux将当前状态(仍然是一个空数组)与action对象一起传递给reducer。action对象现在有一个值为1ADD_USER的type属性,让reducer知道如何更改状态。redux正式登场在src下创建一个redux,actions,data(存放一些初始数据)文件夹,然后在data文件夹下创建一个db.js,在这个文件中写入一些初始数据:src/data/db.jsconstdata=[{id:1,title:'明天我要打酱油',content:'一起打酱油吧'},{id:2,title:'周末去书店',content:'书是人类进步的阶梯'},{id:3,title:'备份数据库',content:'备份服务器的数据库,一般是独立的,分布式的数据库'},{id:4,title:'周五记得洗被子',content:'洗杯被子被子被子'},{id:5,title:'Plan5',content:'Plan5content'}]exportdefaultdataOk,初始数据我们有了它,下面就是创建一个store。在redux文件夹下,创建一个planlist.js文件。这个文件就是operationstore的action动作集合处理后的数据。这个时候我们在action文件夹下新建一个,action-type.js和plan.js,代码如下:src/action/action-type.jsexportconstADD='ADD';exportconstDELECT='DELECT';exportconstSHOW='SHOW';src/action/plan.jsimport*astypesfrom'./action-type.js';//添加计划导出函数addPlan(item){return{type:types.ADD,item};}//删除计划导出函数deleteplan(id){return{type:types.DELECT,id};}//显示和隐藏弹出层导出函数show(show){return{type:types.SHOW,show};}action我们都定义好了现在我们可以换店了编写我们的reducersrc/redux/planlist.jsimport*astypesfrom'../actions/action-type.js';importdatafrom'../data/db.js'constinitialState={show:false,//是否显示弹出的计划列表:data//初始计划列表};constplanReducer=function(state=initialState,action){letlist=state.planlist;switch(action.type){//添加计划案例types.ADD:list.push(action.item);返回Object.assign({},state,{planlist:list});//删除计划案例types.DELECT:letnewstate=list.filter((item)=>item.id!=action.id);返回Object.assign({},state,{planlist:newstate});//显示和隐藏弹出层casetypes.SHOW:returnObject.assign({},state,{show:action.show});}returnstate;}exportdefaultplanReducer;在redux下创建reducers.js和store.js,src/redux/reducers.jsimport{combineReducers}from'redux';//Reducersimportplanlistfrom'./planlist';//合并Reducersvarreducers=combineReducers({planlist:planlist});导出默认值ultreducers;src/redux/store.jsimport{createStore}from'redux';importreducersfrom'./reducers.js';conststore=createStore(reducers);exportdefaultstore;这将完全创建我们的商店下面是把store和我们的组件完全结合起来,这里用到了react-redux的connect模块。这个东西是连接组件和商店的模块。然后,App.js加入我们的。storesrc/App.jsimportReact,{Component}from'react'import{BrowserRouterasRouter,Route,Link}from'react-router-dom'//导入storeimport{Provider,connect}from'react-redux';importstore从'./redux/store.js'从'./logo.svg'导入徽标从'./components/plan.js'导入计划从'./components/home.js'导入主页从'./components/pupop.js'importTestRouterfrom'./components/testrouter.js'importDetailfrom'./components/detail.js'import'./App.css'import'./components/comment.css'importcreateHistory来自'history/createBrowserHistory'consthistory=createHistory()classAppextendsComponent{constructor(props){super(props);}render(){return(//store的挂载
