Redux 简介
了解 Redux 及其发展历程。
什么是 Redux?
Redux 是一个用于管理应用状态的库。它提供了一种可预测的方式来管理应用程序的不同状态。最初,Redux 是作为 React 框架的一部分设计的,但如今已不再局限于 React。该库因其在处理具有大量变量的复杂应用时的强大功能和易用性而受到广泛赞誉。
为什么应在学习 NgRx 之前先学习 Redux?
NgRx 是 Redux 的扩展,增加了更高级的功能,如选择器(selectors)、Observables 和 Effects 模型。NgRx 提供了一些额外工具,用于优化应用,例如处理副作用操作,如从 API 获取数据或在每次动作发生时更新用户界面。因此,我们应该先学习 Redux,因为相比 NgRx,Redux 更容易理解。
什么是 Flux?
Redux 基于 Flux 架构。Flux 是一种用于构建前端应用的架构模式。该概念由 Facebook 在 2014 年的 F8 大会上提出。
为什么需要 Flux?
传统的 MVC:模型-视图-控制器(MVC)是一种用于在计算机上实现用户界面的软件架构模式。该模式将界面分为三个部分:模型(负责数据处理)、视图(负责向用户展示数据)以及控制器(负责处理用户输入)。
MVVM:MVVM(模型-视图-视图模型)是一种软件开发中的设计模式,旨在清晰地分离视图与模型。视图负责显示数据并处理用户输入,而模型则负责管理数据和逻辑。
双向数据绑定:双向数据绑定是一种机制,使视图与模型相互关联。当其中一方发生变化时,另一方会自动同步更新。这些模式会导致 级联更新,即一次用户界面的更改会自动触发另一个用户界面(UI)的更新。这在应用性能方面极为低效。为了更好地理解级联更新的概念,我们来看一个示例场景:
在我们的应用中,多个组件可能需要相同的数据。如果其中一个组件修改了数据,我们就需要更新其他相关组件以保持一致性。在一个大型应用中,我们可能不得不通过“提升属性”和“属性传递”来更新所有目标组件。
- 属性提升(Prop-lifting):将更新后的数据逐级传递给父组件,直到到达目标组件或根组件。
- 属性传递(Prop-drilling):将数据逐级传递给子组件,直到到达目标组件。
以下幻灯片展示了这些概念的可视化效果:
重要的是要认识到,如果没有合适的状态管理策略,更新应用中所有组件将非常低效。为了解决这个问题,Facebook 开发者提出了一种单向数据流模式,确保 UI 变化不会引发级联更新。
Flux 架构
在 Flux 应用中,数据流动方向单一,如下图“Flux 中的单向数据流”所示。这是 Flux 架构的主要特点之一。
动作(Action)
动作 是一个简单的 JavaScript 对象。它包含更新后的数据以及需要执行的操作类型,用于改变状态。动作会将这些信息发送给分发器(dispatcher)。
分发器(Dispatcher)
在 Flux 应用中,所有数据都通过一个唯一的 分发器 函数流动。一个 Flux 应用不能有多个分发器。其主要职责是调用存储(store)注册的相应回调函数,并维护应用中多个存储之间的依赖关系。
存储(Store)
我们把整个应用的状态保存在 存储 中。在 Flux 应用中,可以存在多个存储。每个存储包含用于修改状态的所有逻辑。状态被修改后,存储会发出一个变化事件。
视图(View)
视图/组件 会订阅所需的变更事件。当存储发出特定事件时,视图会使用新数据自动更新自身。视图也可以通过用户交互触发动作。
Redux 的诞生
2014 年,Facebook 在 F8 大会上宣布了 Flux 后,全球开发者纷纷开源了自己的实现。因此,围绕这一模式出现了许多不同的 npm 库。
其中最受欢迎的是 Redux。 Dan Abramov 在 2015 年的 ReactEurope 大会上首次介绍了 Redux。
Flux 与 Redux 的对比
尽管 Redux 基于 Flux,但两者存在一些差异:
- Redux 使用单一存储来管理应用中所有组件的数据,有助于保持状态的一致性。这使得 Redux 比允许多个存储的 Flux 更简单。
- 在 Flux 中,使用中心化的分发器将所有动作分发给所有注册的存储;而在 Redux 中,无需分发器,因为存储可以直接处理动作。这带来了更高的灵活性、可扩展性以及更简洁的代码结构。
- Flux 的存储可以直接修改状态,而 Redux 的存储不能直接修改状态。在 Redux 中,我们使用 Reducer 来处理状态的变更。