dojo dragon main logo

状态管理

企业应用程序通常需要其状态随着时间的推移而持久化,并允许用户以各种方式查看和操作这些数据。当需要跨多个位置并发访问和编辑相同数据,同时保持一致性时,状态管理可能会成为大型应用程序中最复杂的领域之一。

状态通常持久化在 Web 应用程序组件外部的数据存储或数据库中,这意味着需要在应用程序外部解决一些状态管理复杂性。但是,对于数据在应用程序及其用户之间流动的实例,几种范式可以帮助最大限度地降低复杂状态管理的风险。

响应式数据修改

以命令式方式编写的应用程序描述了要更改哪些数据、更改方式以及指定更改发生的时间和位置。如果几块数据通过某种形式的计算或赋值逻辑连接,它们的连接只在某个离散时间点表示。在此时间点之外,任何数据值都可能以违反其预期逻辑连接的方式发生更改。

以响应式方式编写的应用程序则试图提升数据之间的逻辑连接,并放弃控制何时何地进行更改的具体方式,而有利于随着时间的推移保持逻辑数据连接的一致性。

具有多个服务层的复杂应用程序可能对同一数据点有更多表示,因为它在应用程序的各个位置流动 - 这种常见模式是使用数据传输对象。随着给定数据可能具有的表示数量呈指数级增长,维护应用程序状态的完整性变得越来越复杂。

任何具有呈现动态状态的 UI 的应用程序 - 包括 Web 应用程序 - 都将遇到维护逻辑数据连接一致性的问题。这些应用程序中的数据点始终至少具有两种表示。

示例问题说明

给定一个存储一组任务的待办事项应用程序,当向用户显示单个任务时,它将具有以下两种数据表示

  • 任务的当前描述(其“真实来源”,例如它在数据存储中的值是什么)
  • 通过 UI 元素(例如标签或文本框)呈现给用户的任务描述的副本。

如果用户只能查看任务,则存在几个与如何使对任务描述的更改对用户可见相关的问题。

如果在底层数据存储中更改了任务,则需要将其新描述传播到 UI,以便用户不会查看陈旧的数据。如果任务在 UI 中的多个位置显示,则需要更新所有实例,以便用户不会在不同位置查看不一致的数据。

如果用户也可以修改任务(例如更改其描述),则需要解决其他问题。

任务描述现在有两个真实来源:数据存储中的旧值和用户在文本框 UI 元素中输入的新值。

然后需要将更改请求传播回底层数据存储,以便用新值替换旧值。更改完成后,需要将新的任务描述发送回用户,以便他们看到包含其更改的正确值。尝试更改任务描述时可能发生的任何错误也需要考虑在此数据交换中。

Dojo 中的状态管理

对于最 基本的状态管理 需求,小部件可以通过本地范围的变量管理其自身状态。虽然这种方法有利于隔离和封装,但它只适用于非常简单的用例,例如在应用程序中单个位置出现的小部件,或者与应用程序处理的所有其他状态断开连接的小部件。

随着对在小部件之间共享状态的需求增加,Dojo 倾向于响应式控制反转。状态可以提升到父容器小部件中,并通过子小部件的 属性接口 注入到包含的子小部件中。如果需要,这种状态提升可以遍历整个小部件层次结构,其中状态集中在根应用程序小部件中,然后将其部分注入到相关子分支中。

对于更复杂的需求,或者对于在其中将状态传递到无关的中间层之间不可取的大型小部件层次结构,外部化数据存储可能是最佳方法。中央数据存储可以帮助处理大量状态的应用程序,允许复杂的状态编辑操作,或者在许多位置需要相同的状态子集。

Dojo 提供了一个 存储 组件,它支持各种高级状态管理需求,例如

  • 对异步命令的固有支持,例如对远程服务进行调用以进行数据管理。
  • 状态操作的确定性排序。
  • 状态操作记录,允许操作回滚/撤消
  • 数据操作过程的中间件包装,用于跨领域问题,例如授权或日志记录。
  • 对基于 localStorage 的数据存储的内置支持,有助于 PWAs。
  • 支持乐观数据更新,在失败时自动回滚