Flux既是当下网页开发中最热门的也是最难理解的话题之一。所以笔者写这个指南的目的是以一种所有人都能理解的方式来解释它。
那么问题来了
首先,我应该先解释一下Flux能够解决的基本问题是什么。Flux是一种处理你的应用里的数据的模式。Flux和React一起在Facebook成长起来。尽管你可以独立使用他们,许多人都是把他们放一起用。他们以前是被开发出来处理Facebook当时遇到的问题的。
在这一系列问题中大家真正熟知的一个就是消息通知bug。你登录到Facebook时,你会看到在消息图标上有一个通知。点击消息图标,然而,并没有新消息出现。通知也会消失。然后,在和这个站点做了一些交互之后几分钟,通知又回来了。你又会点击消息图标……仍旧没有新消息。这个问题就是继续在这个循环中往复出现。
这并不仅仅对于站点用户是一个循环。对于Facebook的团队来说也是。他们会修复这个bug,事情会进展正常一会儿,然后这个bug又回来了。它会在被解决和又变成一个问题之间来回往复。
因此Facebook就开始寻找摆脱这个循环的方法。他们不想仅仅一次性修复这个bug。他们想要使系统可控,这样他们就能确保这个问题不再继续浮出水面。
根本问题
他们确定的根本问题是数据在app中流动的方式。
注释:这是我从他们已经在讨论中分享的简明版中收集到的。我确定真正的结构看上去不同。
他们具有持有数据并传递数据到视图层来渲染数据的模型。
因为用户交互是在视图上发生的,视图有时候需要在用户的输入内容基础上更新模型。而且有时候模型需要更新其他模型。
最重要的是,有时候这些action会出发一系列其他改变。我把这想象成一个“接乒乓球游戏”——很难知道球将要在哪里落地(或者从屏幕掉落)。
事实上这些改变可能是异步发生的。一个改变可能出发多个其它改变。我把这个想象成抛出袋子里所有的乒乓球到你的接球游戏中,伴随他们的是四处乱飞和交错的轨迹路线。
总之,这使调试数据流变得很难。
解决方案:同一方向的数据流
因此Facebook决定尝试一种不同的架构,在这个架构里数据按照一个方向流动——仅仅一个方向——而且当你需要插入新数据,流动在初始处从头再开始。他们称他们的架构为Flux。
这事实上非常酷……但是你可能不能从上面的图表上看出来。
一旦你理解了Flux,这个图表就灰常清楚明了了。问题是如果你去查阅最新的Flux文档,我不认为这个图表会帮助你理解它……这却是一个图表应该做到的。当你真正开始深入研究怎样做特定事情之前,它应该给你一个大图来理解一个系统。
帮我更好地理解Flux的并不是像这样的图表,而是想出按照不同角色作为一个团队协作来达成同一个目标的系统。所以我想要向你介绍在我脑子里的全部角色的演员表。
围观一下角色
我这就在解释他们怎么交互之前先快速介绍一下所有角色。
action制造器
第一个角色是action制造器。所有改变和交互都通过它负责制造的action来完成。无论你什么时候想要改变应用的状态或者让视图渲染差异化,你都会产生一个action。
我把action制造器想成一个电报员。你基本上知道你需要发送的信息的时候去找action制造器,接着action制造器按照后续系统能理解的方式格式化你的信息。action制造器制造了一个带有类型和有效信息的action。这个类型将会是你已经在你的系统中定义好的action类型(通常是一个常量列表)中的一个。举个例子,类似MESSAGE_CREATE或者MESSAGE_READ。
这会带来一个好处,那就是通过了解你系统的一部分就可以简单地了解到所有系统可能的action。新的程序员进入这个项目,打开action制造器的文档然后看一下整个API——所有可能的状态变化——你系统提供的。
当它已经制造好了action信息,action制造器就会传递这个action到分发器。
分发器
分发器基本上是一个大的回调函数注册表。它有点像在一台电话转换板旁的电话接线员。它有一个写有需要发送action过去的全部仓库(数据存储仓)的清单。当一个action从action制造器那过来的时候,它会散播action到不同的仓库。
它用异步的方式做这件事,这样会对我前面说过的多球的接球游戏的影响有帮助。而且如果你需要在不同的仓库之间建立依赖关系来做到使一个在另一个之后更新,你可以通过分发器用waitFor()来实现。
Flux的分发器跟很多其他分发器不同。不管action是什么类型,都会被发送到所有注册过的仓库。这意味着仓库不仅仅订阅某些action。它监听所有action并且会区分出哪些是它关心和不关心的。
仓库
接下来是仓库。仓库保存应用中的所有状态,和所有在这些仓库中的应用状态改变的逻辑。
我把仓库想象成一个过度控制的官僚主义者。所有状态的变化必须被它个人完成。而且你不能直接请求它改变应用状态。在仓库没有设置器。想要改变状态,你必须遵循恰当的流程……你必须通过action制造器/分发器的传递途径提交一个action。如上所述,如果一个仓库在分发器中注册过,所有action都会被传给它。在一个仓库里通常有一个 switch语句,它通过这个action的类型来决定是否该仓库应该关心这个传进来的action,它会区分出基于这个action什么变化需要被执行并会更新状态。
仓库一做好针对状态的变化就会发出一个改变事件。它会通知视图控制器状态已经改变好了。
视图控制器和视图
视图是负责获取状态和为用户渲染状态的,当然也接收用户的输入。
视图层是一个主持人。它不清楚这个应用的任何事,它只知道传给它的数据和怎样排版输出数据让人们理解(通过HTML)。
视图控制器像个在仓库和视图之间的中层经理。仓库状态改变的时候会告诉它。它收集新的状态然后传递更新过的状态到它控制下的所有视图。
他们在一起怎样工作的
所以,让我们看一下所有的角色是如何工作的。
设置
首先,会有一个设置:只发生一次的应用初始化。
1.仓库告诉分发器他们想要在一个action在任何时候进来都被告知。
2.然后视图控制器向仓库索取最新的状态。
3.当仓库把状态给了试图控制器,他们就把状态传给他们的子视图们去渲染。
4.当状态改变的时候,视图控制器也要求仓库让他们知道。
数据流
设置成功后,应用就准备好接收用户的输入了。因此让我们通过让用户做一个改变触发一个action。
我们会通过一个用户交互开始一个数据流。
1.视图告诉action制造器去准备一个action。
2.action制造器格式化action并把它传给分发器。
3.分发器发送action到队列里的仓库。每一个仓库都会拿到所有的action的通知。然后仓库决定是否要关心收到的action,并会有依据地更新状态。
4.当仓库的状态改变完成就会通知订阅他的视图控制器。
5.那些视图控制器紧接着会请求仓库给他们更新过的状态。
6.在仓库把状态给了视图控制器,它就会让它的子视图基于最新的状态渲染。
以上就是我怎么看Flux的。希望对大家有帮助!
附:原文链接https://code-cartoons.com/a-cartoon-guide-to-flux-6157355ab207?token=Yjf8sIYOsAIJ3A8s#.s2yxabta5
前端翻译新手一枚,部分话略显生硬,欢迎网友给予意见或建议!