几年前,对很多人来说,开发个前端应用程序就像是小菜一碟。而现在,前端应用程序的复杂性日益增长的趋势几乎势不可挡。
看起来,为了满足要求苛刻的用户的迫切需求,这只温柔可爱的猫已经变成一头无畏的狮子,有尖利的长爪和血盆大口。
是的,现代前端开发就是这样。
像Angular、React和Vue这样的现代框架在驯服这头野兽方面做得很好。同样,现代哲学(比如Redux执行的哲学)也给这头野兽打了一剂镇定剂。
下面我们来看看这些哲学。
Redux是什么?
Redux的官方文档如下:
Redux是一个针对JavaScript应用程序的可预测的状态容器。
第一次阅读这一行字时,我是没有搞懂的。估计你也一样。
别头大。后面我们会回头再研究这句话,而且随着使用Redux越来越多,这句话会逐渐变得清晰起来。
继续往下阅读文档,我们会看到文档中解释说:
它可以帮助您编写行为一致的应用程序…
看到了这段话了吧?用俗话说,这就是暗示,它可以帮助你驯服这头野兽!
Redux消除了在大型应用程序中状态管理所面临的一些麻烦。它为我们提供了出色的开发体验,并确保应用程序的可测试性不会因任何这些问题而受到损失。
在开发React应用程序时,你可能会发现把所有状态都放在顶层组件中已经不够了。随着时间的推移,应用程序中也可能会有大量数据发生变化。
Redux有助于解决这些问题。请注意,这不是唯一的解决方案。
为什么用Redux?
一般来说,像为什么应该使用A而不是B这类问题大部分是由于个人偏好。比如,有很多人创建了不少不使用Redux的应用程序。很多人是担心用Redux会给团队成员添加一层额外的复杂性。
Redux的作者Dan Abamov也警告不要过早把Redux引入到应用程序中。
你可能不喜欢Redux,这没什么错。不过,话虽这么说,学习Redux还有一些很不错的理由。
比如,在有大量活动小组件的较大型应用程序中,状态管理成了大问题。Redux在不牺牲性能或者可测试性方面表现得相当好。
很多开发人员喜欢Redux的另一个原因是它带来的开发体验。有很多其他工具已经开始做类似的事情,不过Redux获得的评价更高。
使用Redux可以获得的一些好处包括日志记录、热加载、时间旅行、同构应用程序、录制和重放操作,而且都不需要开发人员做得太多。这些玩意可能听起来很花哨,不过如果你开始使用它们,并亲眼看到效果,慢慢就会明白。Dan有一个热加载与时间旅行的演讲会让你很好地了解这些功能是如何做到的。
此外,Redux的维护者之一Mark Ericsson表示,超过60%的React应用程序在生产中使用Redux。很多工程师喜欢向潜在的雇主展示他们可以维护用React和Redux创建的更大的生产代码库,所以会学习Redux。
Redux的创建者Dan在他的文章中也突出强调了一些理由。
如果你认为自己还算不上高级工程师,那么建议学习一下Redux,主要是因为Redux所教授的一些原则,这会让你学习做常见事情的新方法,从而会让你成为一名更好的工程师。
向5岁娃娃解释Redux
本书的这一部分非常重要。这里的解释将在本书中被引用。所以请准备好。
我们来考虑一个大家都熟悉的事件 - 去银行取钱。
小明早上起床去银行。在去银行时,他心里有一个意图/动作:WITHDRAW_MONEY(取钱)
。
这是事情开始变得有趣的地方。
小明进入银行时,会直奔银行柜员,让柜员知道他的要求。
等等,去见银行柜员?为什么不直接进入银行金库拿钱呢?
毕竟这是小明自己辛辛苦苦挣的钱啊。
好了,我们都知道,这事不能这么干。是的,银行金库里有钱,但小明必须和银行柜员交谈,按正当程序取回自己的钱。然后收银员从他们的电脑输入一些命令,并把钱交给小明。非常简单。
那么,Redux如何融入这个故事?
我们先看看术语。
- 银行金库对银行来说,就是
Store
对Redux。
银行金库存放银行里的钱,对吗?是的,在应用程序中,我们没有花钱。不过,应用程序的state(状态)
就像我们花的钱。应用程序的整个用户界面是状态的一种表现。
就像银行金库保证我们的钱在银行中安全一样,应用程序的状态通过store
保证安全。所以,store
保证你的钱
或state
完好无损。
记住:Redux Store可以比作银行金库。它保存应用程序的状态 - 并且保证它的安全。
这就引出了第一条Redux原则:
只有单一数据源:整个应用程序的状态都是以对象树的形式存储在唯一的store中。
别被这些词搞糊涂了。简单点讲,用Redux时,建议将应用程序的状态统一存储在一个由store
所管理的对象中。就好比是把钱放在一个金库中,而不是把钱乱放在银行大厅的各个地方。
- 带着一个意图/动作去银行。
你去银行,是带有一个意图/动作的,就是去取钱。如果只是到银行散步,没人会给你钱,最终还可能被安保人员扔出去。
对于Redux也是一样。随便你想写多少代码,但是只要你想更新你的Redux应用程序的状态(像在React中用setState()
一样),你得让Redux知道这种带有一个意图的状态更新。
与遵循正常流程从银行取钱方式一样,Redux也负责一个正常流程来修改/更新你的应用程序的状态。
现在,这就引入了第二条Redux原则。
状态是只读的:修改状态的唯一方式是发送一个action,action是一个描述发生了什么事的对象。
用简单的语言表达的话,这是什么意思?
当你去银行时,你是带着清晰的意图/动作的。在本例中,你是想取一些钱。如果我们在一个简单Redux应用程序中表示这个流程,你到银行的意图/动作可能是被一个对象来表示。这个对象看起来像这样:
{type: "WITHDRAW_MONEY", amount: "$10,000"}
在一个Redux应用程序的上下文中,这个对象被称为action
!它总是有一个type
字段描述我们想执行的动作。在本例中,它是WITHDRAW_MONEY
。
只要你想修改/更新你的Redux应用程序的状态,就需要发送一个action。
现在不要强调如何做到这一点。我只在这里奠定了基础。我们很快就会深入研究很多例子。
- 银行柜员对银行,相当于
reducer
对Redux。
好了,退后一步。
还记得吧,在上面的故事中,我们不能直接到银行金库从银行拿钱。我们必须先见银行柜员。
是的,你心里有一个动作,但是你必须将这个动作传达给某人 - 银行柜员 - 然后银行柜员与存有银行所有钱的银行金库沟通。
Redux也可以这么说。就像你让你的动作让银行柜员知道一样,在你的Redux应用程序中你必须做同样的事。如果想更新应用程序的状态,就要把你的action
传达给我们自己的银行柜员reducer
。这个流程通常称为发送(dispatch)一个action
。
dispatch只是一个英文单词。在本例中,以及在Redux领域,它被用来指派遣一个动作给reducer。
reducer
知道要做什么。在本例中,它会采取你的动作去WITHDRAW_MONEY
,并确保你拿到钱。
在Redux术语中,你花的钱就是状态
。所以,你的reducer知道要做什么,并且它总是返回你的新状态
。
嗯。这就没那么难理解,对吧?
而这引入了最后一个Redux原则:
为指定状态树如何根据动作(action)来做改变,我们得编写纯归纳函数(reducer)。
我们会逐步解释”纯”归纳函数(reducer)是什么意思。目前最重要的是理解:要更新你的应用程序的状态(就像在React用setState()
一样),你的action必须总是被发送给归纳函数reducer,以得到新状态。
用这种类比,你现在应该知道最重要的Redux角色是什么:store(仓库)
、reducer(归纳函数)
和action(动作)
。这三个角色对于任何Redux应用程序都是关键。一旦你理解了它们的工作原理,大部分事就搞定了。