65.9K
CodeProject 正在变化。 阅读更多。
Home

为什么要在前端代码中使用状态管理?

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.53/5 (7投票s)

2021年8月17日

CPOL

4分钟阅读

viewsIcon

18176

在前端代码中使用状态管理的好理由

摘要

在前端代码中使用状态管理的良好理由是:

  • 作为数据库缓存
  • 用于广播消息
  • 用于集中处理加载指示器

引言

所有状态管理工具都遵循相同的原则:

  • 一个Store(存储),这是一个可以从代码任何地方访问的全局数据存储。
  • Actions(操作):Store 中的数据通过分派(dispatch)一个Action来更新。可以将它想象成一个Setter(设置器),数据(或状态)通过Action设置
  • Getters(获取器):如果你有 Setters,你肯定需要 Getters,对吧?然而,只有在 Vuex 中才使用“Getters”这个概念通过name来调用。在 Redux 和 NgRx 中,有selectors(选择器),或者对于 Redux 类组件,如后面所示,会使用mapStateToProps这样的构造。

以下状态管理工具常与相应的库一起使用:

  • React & Redux/Recoil
  • Angular & NgRx(与 Redux 非常相似)。
  • Vue & Vuex
  • Blazor & Fluxor

当我第一次听说状态管理时,我不理解它要解决什么问题,并且我想知道它为什么是必需的。我已经开发了很多 Web 应用程序,但从未遇到过“状态”问题。ReactJS 中的 Redux 感觉相当不必要,而且,Redux 的创始人 Dan Abramov 自己也说过,在使用 Redux 之前,你应该确保 Redux 真的有必要。

你可能不需要 Redux。人们经常在…之前选择 Redux | 作者:Dan Abramov | Medium

这句话加深了我对 Redux 优越性的疑虑,不使用 Redux 构建 React 应用也很好,Redux 只是增加了不必要的复杂性。

然而,当我开始使用 Vue.js 和 Vuex 时,我意识到了状态管理的优势。Vue.js 是一种很棒的语言,可以看作是 React 和 Angular 的进一步发展。当你编写 Vue.js 代码时,你会很快意识到 Vuex 无疑会帮助你。

数据库缓存

数据库缓存通过减轻数据库的压力来补充你的主数据库,通常是通过频繁访问的读取数据。大多数 Web 应用程序都有数据库。Store 有时被称为“单一事实来源”(single source of truth),但我认为数据库才是“单一事实来源”。Store 仅仅是数据库的一个缓存。

然而,有一个特定的问题让我理解了状态管理的用处,那就是“广播消息”。

通过状态管理进行广播消息

广播消息是指让一个组件向许多其他组件发送消息。其他组件可以位于应用程序组件树的任何位置。通常,组件之间的通信遵循“从父到子”的模式。在广播消息的情况下,这是“一对多”模式。

“一对多”通信的需求迟早会在大多数应用程序中出现。这可以通过多种方式实现,但我认为最简单、最清晰的方式是使用状态管理。事实上,很久以前,我曾写过一篇关于Angular 中的广播消息的文章,当时未使用 NgRx。今天,我可能会选择 NgRx 来实现此目的。

通过状态管理控制加载指示器

第二个使用状态管理的理由是其集中处理加载指示器的好处。在每个前端应用程序中都应该使用加载指示器来表明正在从服务器获取数据。程序员经常在每个组件中引入一个本地状态标志,而不是使用状态管理中的一个单一标志。

我注意到在 Vuex、Redux 和 NgRx 的教程中,有一个状态被用作状态标志,其值通常是‘idle’(空闲)和‘loading’(加载中)。强烈建议使用这个状态标志,并结合例如 Font Awesome 的旋转图标,来指示正在从后端检索数据。

ReactJS/Redux 示例

使用的 Font Awesome 旋转图标:https://fontawesome.com/v5.15/icons/spinner

此代码来自一个React 类组件

<FontAwesomeIcon
    icon={faSpinner}
    size={'2x'}
    spin
    style={this.props.status === 'idle' ? {opacity:'0'}:{opacity:'1'}} />

在这里,状态标志名为“this.props.status”,并通过mapStateToProps构造进行检索。

const mapStateToProps = state => ({
   …
  status: state.photos.status
});

在使用了 React Hooks 的React 函数式组件中,使用useSelector访问状态标志,如下所示(简化版):

Import
…
  selectUserStatus
} from './userSlice';

const status = useSelector(selectUserStatus);

<FontAwesomeIcon
   icon={faSpinner}
   size={'2x'}
   spin s
   style={status === 'idle' ? {opacity:'0'}:{ opacity:'1'}} />

如今,我认为在 React 中不使用 Redux(或 Recoil),或在 Vue.js 中不使用 Vuex,都是没有借口的。由于 Angular 具有双向数据绑定,因此状态管理似乎很少与 Angular 一起使用。但是,关于 Angular 中的广播消息,请参阅文章Angular 中的广播消息

我期待看到你的评论!

历史

  • 2021年8月17日:首次发布
  • 2022年1月16日:添加了数据库缓存注释
© . All rights reserved.