ReactJS学习系列课程附加(Flux应用架构)

x33g5p2x  于2022-03-06 转载在 其他  
字(2.8k)|赞(0)|评价(0)|浏览(284)

React相对于传统HTML5框架来讲,不同点在于React使用了Flux架构。

Flux是Facebook用来构建用户端的web应用的应用程序体系架构。它通过利用数据的单向流动为React的可复用的视图组件提供了补充。相比于形式化的框架它更像是一个架构思想,不需要太多新的代码你就可以马上使用Flux构建你的应用。

Flux应用主要包括三部分:dispatcher(调度者)、store(仓库)和views(视图—React components),千万不要和MVC(model-View-Controller)搞混。Controller在Flux应用中也确实存在,但是是以controller-view的形式。view通常处于应用的顶层,它从stores中获取数据,同时将这些数据传递给它的后代节点。另外,action creators - dispatcher辅助方法 - 一个被用来提供描述应用所有可能存在的改变的语义化的API。把它理解为Flux更新闭环的第四个组成部分可以帮助你更好的理解它。

Flux使用单向的数据流动来避开MVC. 当用户与React视图交互的时候,视图会通过中枢dispatcher产生一个action。然后大量的保存着应用数据和业务逻辑的视图接收到冒泡的action,更新所有受影响的view。这种方式很适合React这种声明式的编程方式,因为它的store更新,并不需要特别指定如何在view和state中过渡。

我们独创性的解决了数据的获取:举个栗子,比如我们需要展示一个会话列表,高亮其中未读的会话,同时展示未读会话的数量。如果用MVC架构的话将很难处理这种情况,因为更新一个对话为已读的时候会更新对话model,然后同样也需要更新未读对话数量model(数量-1)。这样的依赖和瀑布式的更新在大型的应用中非常常见,导致错综复杂的数据流动和不可预测的结果。(这其实是Facebook之前的一个线上bug,有时候用户看到提示说有一条未读信息,但是点进去却发现没有)。

反过来让 Store 来控制:store接受更新,并在合适的时机处理这些更新。而不是采用一贯依赖外部的方式来更新数据。在store外部,并没办法看到store内部是如何处理它内部的数据的,这样的方式保证了一个清晰的关注点分离。Store并没有类似setAsRead()这样直接的setter方法,但是在其自成一体的世界中拥有唯一个获取新数据的方法 - store通过dispatcher注册的回调函数。

这种的响应式编程,或者更准确的说数据流编程亦或基于数据流的编程,可以使我们很容易去推断我们的应用是如何工作的。因为我们的应用中数据是单项流动的,不存在双向绑定。应用的状态只保存在store中,这就允许应用中不同部分保持高度的低耦合。虽然依赖在store中也确实存在,但他们之间保持着严格的等级制度,并通过dispatcher来管理同步更新。

我们发现双向绑定会导致瀑布式的更新,一个对象发生变化会引起另一个对象的改变,并可能导致更多的更新。随着应用的增大,这些瀑布流式的更新方式会使我们很难预测用户交互可能会导致的改变。当更新只能以单一回合进行的时候,系统的可预测性也就会变得更高。

让我们来看看Flux的各个部分。先从diapatcher开始会比较好。

Dispatcher

dispatcher 就像是一个中央的集线器,管理着所有的数据流。本质上它就是 store callback 的注册表,本身并没有实际的高度功能。它就是一个用来向stores分发actions的机器。 每一个 store 各自注册自己的 callback 以提供对应的处理动作。当 dispatcher 发出一个 action 时,应用中所有的store都会通过注册的callback收到这个action。

随着应用的增长,dispatcher会变得更加必不可少,因为它能够指定注册的callback的执行顺序来管理store之间的依赖。store可以被声明等待其他store完成更新之后,再执行更新。

Facebook目前在生产环境中使用的flux可以分别在npm, Bower,or Gihub中获取。

Stores

Stores 包含了应用的状态和逻辑,它有点儿像传统MVC中的model层,但是却管理着多个对象的状态 - 他们不像传统的ORM model 只管理单个的数据记录,和backbone中的collection也不一样。

举个栗子,Facebook的回看视频编辑器使用TimeStore来保存播放时间和播放状态。另外,应用中的ImageStore保存着图片的集合。再比如说我们的TodoMVC示例中,TodoStore也类似地管理着to-do items的集合。store典型的特征就是既是models的集合,又是所属业务域下的model实例。

就像上面所说的,store在dispatcher中注册,并提供相应的回调。回调会接收action并把它当成自己的一个参数。当action被触发,回调函数会使用switch语句来解析action中的type参数,并在合适的type下提供钩子来执行内部方法。这就允许action通过dispatcher来响应store中的state更新。store更新完成之后,会向应用中广播一个change事件,views可以选择响应事件来重新获取新的数据并更新。

Actions

dispatcher提供了一个可以允许我们向store中触发分发的方法,我们称之为action。它包含了一个数据的payload。action生成被包含进一个语义化的辅助方法中,来发送action到dispatcher。比如,我们想更新todo应用中一个todo-item的文本内容。我们会在TodoActions模块中生成一个类似updateText(todoId, newText) 这样的函数,这个函数可以被视图事件处理调用执行,因此我们可以通过调用它来响应用户交互。action生成函数同样会增加一个type参数,根据type的不同,store可以做出合适的响应。在我们的例子中,这个type可以叫做TODOUPDATETEXT。

一个payload大概是这个样子的: { source: “SERVER_ACTION”, action: { type: “RECEIVE_RAW_NODES”, addition: “some data”, rawNodes: rawNodes } }

Actions也可能来自其他地方,比如服务器端。这种情况可能会在数据初始化的时候出现,也可能是当服务器视图更新的时候返回了错误的时候出现。

官网信息介绍: http://facebook.github.io/flux/docs/overview.html

相关文章