在WEB1.0时代,数据改变与页面刷新的机制比较简单粗暴:“后端改变state,前端整个页面view刷新”;前端
web2.0时代,咱们但愿:react
“改变state,view自动更新”web
浏览器里的DOM tree克隆一份完整的镜像到内存,也就是所谓的“virtual DOM”,编程
当页面的state发生变化之后,根据最新的state从新生成一份virtual DOM(至关于在内存里“刷新”整个页面),将它和以前的virtual DOM作比对(diff),而后在浏览器里只渲染被改变的那部份内容,这样浏览器的性能损耗和用户体验不就都不成问题了吗?redux
**在绝大多数的WEB开发中:**js引擎的性能和内存彻底没有被充分利用,咱们正好能够火力全开,利用js的这部分性能红利,实现内存中virtual DOM的diff工做,完美!后端
react很是具备表达力的jsx语法和完善的模块化结构,设计模式
view的组件化和模块化很是有利于分工协做、代码的积累复用以及单元测试,浏览器
伴随着reactJS 前端框架的崛起,redux这些专一于管理state的轻量级框架横空出世;bash
*因为React的“state-view”模式可让开发者的大脑获得一种“单向流”的温馨体验。那为何单向流的思惟状态更加温馨呢?前端框架
这是由于在单向流状态下,要解决的问题如同一个函数映射,已知什么(好比state)是固定不变的,要获得什么(好比view)是定义明确,而人的思惟很是习惯于这种定义明确的、没有“分叉”和“环路”的函数式问题。
页面呈现的state能够经过模块属性(props)从父模块传递到子模块。这种"树状"分流机制,有点像植物将营养(state)从根部不断运输到细枝末叶的过程*
Flux思想:
flux设计模式就是解决以上model-view混乱=>
如今咱们又能够从服务器端的MVC模式中得到灵感了!
由于咱们注意到,服务器端的controller一般也须要对不少Model产生修改,但在代码结构中却集中在一块儿,没有散落一地。缘由很简单:
对比之下,咱们马上发现上述代码片段中前端MVC模式的“痛点”所在:不是MVC模式错了,而是咱们压根缺乏了一个和用户交互行为有关的action抽象!所以,对model的具体操做才无法从各个view组件中被剥离出来,放到一处。
参考http请求,咱们将要定义的action,须要一个typeName用来表示对model操做的意图(相似于http请求的url路径),还可能须要其余字段,用来描述怎样具体操做model(相似于http请求的参数)。
也就是说,当用户在view上的交互行为(例如点击提交按钮)应当引发Model发生变化时,咱们不直接修改model,而是简单地dispatch一个action(其实跟常见的event机制没有什么区别)以表达修改model的意图,这些action将被集中转移给数据端(models),而后数据端会根据这些action作出须要的自我更新。同时,咱们考虑到react中view组件的树状分流结构,因此有以下图所示:
稍微总结一下:从代码层面而言,flux无非就是一个常见的event dispatcher,其目的是要将以往MVC中各个View组件内的controller代码片段提取出来放到更加恰当的地方进行集中化管理,并从开发体验上实现了温馨清爽、容易驾驭的“单向流”模式。 因此我以为,Flux与其说是对前端MVC模式的颠覆,倒不如说是对前端MVC思想的补充和优化。
但为了区分于以往的MVC模式,并向facebook的贡献表达敬意,后面咱们将把这种优化后的 Model-View-Controller 开发模式在React背景下正式称为Flux模式
问题:
React的能够经过View Component把页面呈现进行“原子化”拆分(即上图中兰色区域的树状分流结构);
Flux打通了State-View的任督二脉(绿色区域),并经过action抽象把用户交互行为
进行了“原子化”拆分;
复制代码
那么联系上面的图示,咱们天然要问数据端(紫色区域)的处理,能否一样被“原子化”拆分?
redux 中的reduce机制,将state端的数据处理进行‘原子化’拆分。redux是来自函数式编程(Functional Programming)的一朵奇葩,听说颇有背景([参考连接](Prior Art | Redux) ) reducer,从代码上说,其实就是一个函数,具备以下形式:
(previousState, action) => newState
复制代码
reducer做为一个函数,能够根据web应用以前的状态(previousState)和交互行为(经过flux中提到的action来表征),决定web应用的下一状态(newState),从而实现state端的数据更新处理。这个函数行为和大名鼎鼎的“Map-Reduce”概念中的Reduce操做很是相似,于是称这个函数为“Reducer”。
"shut up and show me the code" redux.js.org/basics/exam…
这里不打算详细讲解Redux的具体使用,而只想经过一个Redux对state数据进行操做的代码片段,管窥一下reducer机制对数据进行拆分和组装的简洁过程。代码片段以下
回味一下,咱们应该能够体会到,这种数据处理“原子化”拆分的方式和react中view组件的拆分有殊途同归之妙,两者都会造成一种“树状”分流结构(在react的view hierarchy中,数据经过props的直接赋值实现单向流;在redux的reducer hierarchy中,数据经过action的函数传参实现单向流)。
visibilityFilter是和列表显示状态相关的另外一个reducer;combineReducers将visibilityFilter和todos合并为整个应用的reducer,也就是todoApp。这个过程,从感受上也和react中view组件的合并过程很是相像。
createStore是一个工厂函数。经过它,todoApp(至关于一个数据处理的引擎)被装配到整个应用的state容器,也就是store中。能够经过store的getState方法获取整个应用的state;同时,store也是一个event dispatcher,能够经过其dispatch和subscribe方法,分别实现触发action事件和注册对action事件的响应函数。总言之,从概念上来讲 Redux = Reducer + Flux
全体亮相
如今React开发模式中的几个核心概念已经所有出场亮相。咱们俯瞰一下整个开发流程:首先,react框架为咱们理顺了 store --> view 的“单向”工做流(store是state的容器);而后,redux框架为咱们理顺了 view --> store 的**“单向”**工做流。而且,react和redux都以组件化的形式能够将各自负责的功能进行灵活地组装或拆分,最大程度上确保咱们“一次只须要专一于一个局部问题”。具体来讲,分为如下步骤:
1.单例store的数据在react中能够经过view组件的属性(props)不断由父模块**“单向”**传递给子模块,造成一个树状分流结构。若是咱们把redux比做整个应用的“心肺” (redux的flux功能像心脏,reducer功能像肺部毛细血管),那么这个过程能够比做心脏(store)将氧分子(数据)经过动脉毛细血管(props)送到各个器官组织(view组件)
2.末端的view组件,又能够经过flux机制,将携带交互意图信息的action反馈给store。这个过程有点像将携带代谢产物的“红细胞”(action)经过静脉毛细血管又泵回心脏(store)
3.action流回到store之后,action以参数的形式又被分流到各个具体的reducer组件中,这些reducer一样构成一个树状的hierarchy。这个过程像静脉血中的红细胞(action)被运输到肺部毛细血管(reducer组件)
4.接收到action后,各个child reducer以返回值的形式,将最新的state返回给parent reducer,最终确保整个单例store的全部数据是最新的。这个过程能够比做肺部毛细血管的血液充氧后,又被从新泵回了心脏
5.回到步骤1
用图示的方式表达:
图中A表示Action,V表示View组件,R表示Reducer。
为了确保咱们比较容易理解程序的全局行为,或者说提升程序行为的肯定性(predictable),咱们通常指望具备相似职能的代码片段被“平铺”着摆放在一。
所以图示中相同颜色区域的代码一般会被放到同一个文件夹/文件中。
另外,一样出于提升程序的肯定性,redux所遵循的函数式编程鼓励咱们使用pure function和immutable。