在没有使用redux时,父子之间可通过props通信,相邻组件之间可以通过共同的父组件通信,但是相隔太远的组件需要层层相递直到找到共同的父组件才可以通信,这样的通信方式很麻烦。
在存在相邻组件联动状态下,很难去同时获取各组件的数据,并且很难确保获取完各部分的数据之后再去执行下一步的时机。
上货部分存在不同信息的配置组件(input,keyInfo,detailInfo,skuInfo)和最外层的控制上传button。要求点击button时获取完四个组件里的数据,然后处理下一步。没有redux的处理方案是:点击button触发getUpload,该函数里会setState saveOption的值,其他四个组件通过componentWillReceiveProps周期检测saveOption变化,从而确定button是否触发,如果触发,调用props里的getKeyInfo方法,把自己组件的数据传给父组件的getKeyInfo,而getKeyInfo里要把得到的数据放在一个公共变量config里,由于不确定组件返回数据的顺序和结束的时刻,需要每个组件传一个自己的标志,每次有一个数组返回数据时都检测公共变量里所有组件的标志,最后一个组件返回时四个标志应该都存在,此时触发之后的事件。
1 | <InputContainer |
通过分析以上场景,我们需要redux更好的管理数据流。
react与传统组件MVC思路不同,react更强调组件化封装,不需要区分mvc,而是把他们以最小组件为单位集中在一起处理。这也是facebook认为react写起来更有优势的一个特点。
而redux+react做了数据流处理的不足之处,在一些很难处理的数据上(以上场景中各组件间很多的联系),redux相当于是做了C这一层的工作。
如果业务逻辑要求操作View的DOM,其实就是对DOM包裹的Model进行操作,例如添加或修改某个li,其本质是要添加或修改li元素中的值,这个值来自于Model。在Redux中,其实就是发起一个action。
执行action的目的虽然是修改Model,不过在Redux中,我们尽量希望遵循FP的思想设计出所谓的“纯函数”,于是Redux就引入了reducer函数,这个函数要做的事情其实就是对Model进行transform(可以考虑引入immutable.js来存储和操作Modle)。一旦Model对象发生了变化(并不是真正发生了变化,而是产生了一个新的Model),Redux就会通知React Component根据新获得的Model去重新Render。
显然,React扮演的是View的角色,Redux则是Controller,至于Model就是Redux Store中存储的State。我们要从MVC模式的角度去思考React+Redux开发,把代码需要做的每件事情想清楚,明确是谁的职责,如此才不至于在实现时走歪路,不讨好地去编写大量View的控制逻辑,尤其是那些牵涉到parent-child组件的递归关系时,可能会让前端代码炖成一锅粥。
本质: 自定义的一个object tree
作用: Action 是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。
结构:type: 行为,以及另一个自定的值。
为了尽量减少在 action 中传递的数据,我们可以创建Action函数来调用,dispatch时只需要调用对应的action函数,和需要传的自定义的值。
全局state的统一存储空间。
Store.getState => 相当于组建内部的this.getState
Store.dispatch(action) => 相当于setState
Store.subscribe(listener) 监听 注销
Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。
纯函数,保持 reducer 纯净非常重要。永远不要在 reducer 里做这些操作:
Redux 首次执行时,state 为 undefined,此时我们可借机设置并返回应用的初始 state。
导航栏鼠标移动显示的菜单栏 (店铺管理,切换店铺,二维码)
1 | { |
开团监控数字的显示