概述
Flux是Facebook用于开发客户端WEB应用程序的产品框架,它利用单向数据流补充反馈UI信息。它更像是一个模式而不是一个正式的框架,并且你还可以使用Flux做快速开发,从而减少编写很多不必要的代码。
Flux由三个主要部分组成:dispatcher、stores、views(反馈组件)。这些不要与Model-View-Controller设计模式搞混。Flux应用程序确实存在控制器(Controller),但他们是控制-视图(controller-view) UI通常在结构的顶层,它接收来自stores的数据并向下传递给它的子结构。此外动作的创建者会调度它的帮助方法(helper methods)来支持一些语义API,这样就可以描述应用程序可能发生的所有变化。他们被有效的认为是Flux更新循环的四部分之一。
Flux避开了MVC设计模式,使用一个单向数据流进行了取代。当用户点击一个具有交互功能的UI的时候,UI会通过中心dispatcher广播一个活动事件,分发到各个stores中,它持有应用程序的数据和业务逻辑,从而更新所有受影响的UI。这种工作方式是特别好的反馈式设计风格,这样允许store发送、更新而不用指明如何过渡UI的两个状态。
我们最初想正确的处理派生数据:例如,我们要为一个消息线程显示未读计数,而另一个界面显示线程列表并且对未读进行标注。这种情况很难运用MVC模式处理---标记单个线程为已读并更新线程模式,并且这时候还需要去更新未读计数模式。这些依赖关系和级联更新通常发生在一个大的MVC应用程序中,导致一个编织交错的数据流并且无法预支结果。
反被stores控制:stores接收更新并以适当的方式处理,而不是依赖于外部使用一些不变的方法去更新。在store之外不会观察到其内部是如何管理自身域数据的,有助与保持一个清晰的分隔关系。Stores没有直接的设置器方法类似setAsRead(),但是取而代之的是仅使用一个方式来获得新数据进入他们的内部世界(self-contained world),回调那些通过dispatcher注册的callback。
结构和数据流
Flux应用程序内部的数据单方向流动:
单向数据流是Flux设计模式的核心,上图应当是Flux程序员的基本心里模式。dispatcher,stores和views是独立的使用不同输入和输出的节点。actions事件是一个包含新数据和标示类型属性的简单对象。
UI与用户交互的时候会产生新的action事件传入系统:
所有的数据流通过dispatcher作为中央枢纽。所有的actions事件通过action creator(action事件创建者)的方法提供给dispatcher,是用户与UI的交互是最为主要的原始来源。这时候dispatcher调用stores先前在其自身注册的callback,调度actions事件到所有的stores中。在他们注册的回调内部,stores会处理任何与他们维护状态相关的actions事件。这时stores会向控制视图(controller-views)发出一个变更事件(change event)的提示,用于提示数据层已经发生了变化。控制视图监听这些事件并且接收来自stores事件句柄中的数据。控制视图调用自身的setState()方法,引发从新重新渲染他们自己,以及所有他们继承树中的子组件。
这种结构在某种程度上让我们很容易理解应用程序,回想反应式功能编程,或更具体的数据流编程或者基础流编程,数据流以单向的方式贯穿应用程序,这里没有双向的绑定流。应用程序的状态仅被stores进行维护,允许应用程序的不同部保持高度解耦。这里依赖stores之间的相互作用,他们被保持在一个严格的层级中,由dispatcher进行同步更新管理。
我们发现双向数据绑定会导致级联更新,这里改变一个对象导致另一个对象也跟着改变,这可能引发更多的更新。随着应用程序的开发,这些级联更新非常难预测在和用户交互中将要发生的结果。当更新仅能改变单向数据流动中的数据,整个系统将变得更加容易预测。
让我们全方位,近距离的观察Flux。dispatcher是一个好的开始。
单个Dispatcher
Stores
stores包含应用程序的状态和逻辑。他们的角色类似于传统的MVC模型,但他们管理很多对象的状态,他们并不扮演类似于ORM模型所做的单一数据记录。他们也不是一样的骨干集合。更不是简单的管理ORM类型对象的集合,stores管理应用程序内部特定 领域应用的状态。UI 和控制-视图
Actions事件
如何调度呢?
case 'TODO_CREATE':
Dispatcher.waitFor([
PrependedTextStore.dispatchToken,
YetAnotherStore.dispatchToken
]);
TodoStore.create(PrependedTextStore.getText() + ' ' + action.text);
break;
waitFor()接收单个dispatcher注册索引列表作为参数,经常称作调度令牌( dispatch tokens)。这时store被waitFor()调用可以依赖另一个store的状态来告知如何更新自己的状态。
PrependedTextStore.dispatchToken = Dispatcher.register(function (payload) {
// ...
});
欲了解更多关于waitFor(),actions事件、action事件创建者和dispatcher,请参看 Flux: Actions and the Dispatcher .