书籍完整目录javascript
这一节将介绍 React 的核心应用架构模式 Flux,包括内容:前端
Flux 介绍java
MVC 架构之痛git
Flux 的理解github
Flux 相关库和工具介绍编程
Flux 与 React 实例redux
最后咱们将会把以前的 TODOMVC 改成 Flux 的架构。segmentfault
简单来说,Flux 是 Facebook 引入到 React 中的一种前端架构,经过定义其核心单向数据流的方式,让 React 应用更加健壮。同时,这种应用架构也具备普适性,能够应用到其余任意前端项目中,甚至能够应用到客户端应用开发中,也就是说 Flux 更应该叫作一种架构模式(Pattern)。后端
在详细介绍 Flux 以前,咱们先来看看传统的前端 MVC 架构以及其带来的问题。架构
MVC 的实现可能有不少种方式,比较灵活,但基本本质不会改变,只是三者间的数据传递方向可能会改变,即使是 MVP 模式也只是 MVC 的变种,因此为了统一咱们且如下图的 MVC 方式来讨论。
Model: 负责保存应用数据,和后端交互同步应用数据
View: 负责渲染页面 HTML DOM
Controller: 负责链接 View 和 Model , Model 的任何改变会应用到 View 中,View 的操做会经过 Controller 应用到 Model 中
关系:Model, View, Controller 都是多对多关系。
以 TODOMVC 为例子用户添加一个 todo 的交互流程:
View -> Action -> Controller -> Model -> View
View -> Action: 添加按钮事件或者 input 输入的提交事件
Action -> Controller: 控制器响应 View 事件
Controller -> Model: 控制器依赖 Model, 调用 Model 添加 todo
Model -> View: View 监听 Model 的改变添加 todo 事件,在 HTML 中添加一个新的 Todo 视图
对于新增一个 todo ,须要编写一个视图渲染处理函数,函数内添加新项目到列表中。同理对于删除一个 todo,也会有一个处理函数。当业务逻辑变多事后,可能有不少模型须要作增删改的功能,与之对应的就是咱们须要精心构建这么多的渲染处理函数。 这种局部更新模式是高性能的关键所在,但问题是:
更新逻辑复杂,须要编写大量的局部渲染函数
问题定位困难,页面的当前状态是有数据和这些局部更新函数肯定的
若是渲染函数只有一个,统一放在 App 控制器中,每次更新重渲染页面,这样的话:
任何数据的更新都只用调用重渲染就行
数据和当前页面的状态是惟一肯定的
重渲染也有弊端,会带来严重的性能问题,重渲染和局部渲染各有好坏,对 MVC 来讲这是一个两难的选择,没法作到鱼和熊掌兼得。
那如何才能兼顾两种模式的优势?
经过 React + Flux
就能够完美解决 MVC 的问题。
重渲染: 在 React 中每次渲染都是重渲染,且不影响页面性能,是由于重渲染的是 Virtual Dom。这就意味着彻底不用去关系重渲染问题,增删改的渲染都和初始化渲染相同入口
数据和状态一致性: Store 的数据肯定应用惟一的状态
简单来讲在 Flux 架构中直接剥离了控制器层,MVC
架构变成了 MV + Flux
架构。
单向数据流
这是 Flux 架构的核心思想,重上面的图中能够看到,数据的流向从action 到 view 的一个单向流。
Action
Action 能够理解为对应用数据修改的指令,任何修改应用数据的行为都必须需经过触发 action 来修改。Action 能够来自于 View,也能够来自服务端的数据更新。
Action Creator:
为了抽象 Action ,提供一些辅助的语义化的方法来建立 Action,这些辅助方法叫作 Action Creator。
Stores
应用的数据中心,全部应用数据都存放在这里控制,同时包含数据的控制行为,可能包含多个 store
Dispatcher
action 的控制者,全部 action 都会经过 dispatcher,由 dispatcher 控制 action 是否应该传入到 store 中,Dispatcher 是一个单例。
View
页面的视图,对应 React 的 Component, 视图能够触发 action 到 dispatcher。
须要区别出一种叫控制器 View(Controller View)的类型,这种 View 能够知晓 store 数据,把 store 数据转化为自身的状态,在将数据传递给其余 view 。 而且能够监听 store 数据的改变,当 store 数据改变事后从新设置状态触发重渲染。 能够将控制器 View 对应 MVC 中的控制器,可是差异很大,控制器 View 惟一多作的事情就是监听 store 数据改变,没有其余任何业务处理逻辑。
一样以 TODOMVC 的添加 todo 为例,Flux 中的流程为:
View -> Action(Action Creator -> Action) -> Dispatcher -> Store -> Controller View -> View
View -> Action: 添加按钮事件或者 input 输入的提交事件,View 中将事件转化为 action, action 由 Action Creator 建立。
Action -> Dispatcher: action 统一由 Dispatcher 分配
Dispatcher -> Store: Dispatcher 分配 action 到 Store
Store -> Controller View: 控制器 View 监听 store 的数据改变,将数据转化为自身属性
Controller View -> View: 数据改变自动重渲染全部视图
渲染策略: 数据改变 Flux 自动渲染,MVC 手动编写更新函数
事件触发策略: Flux 中全部 action 交给 dispather 分配,MVC 中交给对应的控制器分配
Flux 在核心策略上的不一样是解决 MVC 架构问题的关键
Flux 架构是很是优雅简洁的,合理利用了一些优秀的架构思惟
数据的处理过程是 Store -> Controller View -> View
。 全部数据来自于 Store,页面的渲染层级为 Store 将数据传入 Controller View, 再由 Controller View 传入子 View , 一直到 View 的叶子节点。
这个是一个典型的分而治之策略,将大的页面拆分为小的模块,再由小的模块拆分为小的组件,具体组件负者组件自身的问题,全部子组件都是自私的,不用关心“你们”,只用关心“小家”。
Flux 把全部的 View 都视做愚民,Store 视做资源的拥有者为统治者,统治者须要提供资源(数据)给平民,可是若是平民企图对资源修改(Mutation),必须得先通知给统治者,让统治者决定是否作处理。
咱们为 Flux 中的概念分配角色
View: 平民
Action: 资源修改操做
Dispatcher: 审核官
Store: 统治者
一个企图修改资源的操做能够描述为:
View Require Mutation -> Action -> Dispatcher -> Store -> Mutate Handler
平民提交 Mutation 请求,由审核官控制,审核经过后递交给统治者,统治者再分配给亲信作资源 Mutation
合而治之的策略也等于中心化控制策略, 做为统治者既要懂得放权利(资源的分配),也要懂得控制权利(资源的修改),这种收缩自如的合理性是 Flux 简洁的根本。
同时这种思惟带来的优势以下:
View 的独立性和简单性:View 自身的逻辑简单,不须要知道太多事情,只关心上级传来的数据,这种模式使得 View 是低耦合的,简洁的。
高可维护性:中心化控制知道全部对资源的操做,若是发生 bug, 能够很快定位问题
在 Flux 中数据的单向流动依赖于 View 的肯定性,相同的数据传入相同的组件,获得的结果必然要相同,这是函数式编程的思想。
函数式编程中的纯函数(Pure Function)定义以下:
纯函数是这样一种函数,即相同的输入,永远会获得相同的输出,并且没有任何可观察的反作用
如:
// 纯函数,相同的输入一定有相同的输出 function pure(a, b, c) { return a + b + c; } // 非纯函数,咱们永远没法肯定 this.a 会变成什么 function notPure(b, c) { return this.a + b + c; }
为了保证组件也能作到 “纯函数” 的特性,相同的属性会获得相同的渲染结果。 在写 React 组件的时候尽可能准守一下约定:
尽可能使用无状态组件
除了控制类组件之外其余组件避免使用组件状态
能够经过属性计算出来的状态不要用状态来表示
组件的渲染避免外部依赖,按照纯函数的方式写
函数式的优势也是无反作用组件的优势:
无耦合,可移植性强: 组件可重用性高
可测试性高:组件无依赖,能够很容易的单独测试组件
上面已经讲过 Flux 更应该算是 Facebook 提出的一种前端架构模式,而根据这种理念的 Flux 实现有不少,如下是 github star 数较高的一些实现:
Redux 目前承认度最高的实现
后面咱们会在第四章中专门讲解 Redux 与 React 的应用。
@todo