angular - 拆分 NGXS 状态为更小、可维护的部分的最佳方法是什么,同时保持它们彼此可访问?
问题简史:
我正在为聚会游戏《狼人杀》开发网页助手,所以目标是将单局游戏存储在 NGXS 中。这是 GitLab 仓库
游戏包含:
- 球员名单
- 经过的天数列表(从0到大约5(通常))
玩家模型
每一天有三个阶段:夜晚 > 白天 > 投票
日间模型
为了维持这个复杂的日程结构并记录所有玩家的行动,我需要非常多的行动,因此当 GameState 开始变得庞大时,我尝试将其分拆成子状态。在这里,我遇到了循环依赖问题。
实际上,我不知怎么地设法解决了它,通过阅读这个:https://github.com/ngxs/store/issues/632
我创建了 CurrentDayState 和 PlayersState 作为子状态,但在这种情况下,这似乎是一个不好的方法,因为这样:
- 我只能直接访问状态,而具有复杂逻辑的选择器此时仍然无法访问。
- 我只存储当前的天数和当前的投票,然后将它们推入
GameState中的 days 数组,如果游戏主持人需要查看一些信息,那么实现回到前几天会很困难
我觉得我的方法有点笨拙,而且我无法想出更好的解决方案。我可以把所有动作都存储在根 GameState 中,但这样 .ts 文件将占用大约 800 行代码,这在我看来是个不好的主意。
问题:
有没有办法让 NGXS 状态模块化,同时让它的每个部分都能访问另一个部分的选择器,而不引发循环依赖问题?(读取已经意味着问题,NGXS 子状态应该彼此独立,且绝不应相互控制)
答案#1
一种处理这个问题的方法是将每个存储视为一个数据库表格,将每个你写入的新状态视为表格中的新记录/行。通过对你的模型进行规范化,你可以拥有一个玩家存储和一个日期存储。如果你需要获取给定日期的所有日期和玩家状态的历史记录,你可以不断插入新状态,而不是更新当前状态。玩家可能需要一个属性来指示该状态的时间(例如一个指向关联日期状态的外键)。
选择器可以被编写为使用当前状态,或者在这是业务需求的情况下,查找游戏历史中的指定时间的状态。ngxs 关于选择器的文档提到了使用元选择器将不相关的状态连接起来。你可以考虑使用这些选择器,将相关的玩家和日期状态为给定的查找需求组合在一起。
编辑 1: 对数据进行标准化并存储快照可以解决你提到的关于拥有完整游戏历史记录和维护更多管理状态的双重问题。
关于在不产生循环依赖的情况下维护不同状态的具体问题,你应该避免将两个文件互相导入。我能想到的两种管理方法是:
考虑你需要将哪些州连接起来——选择其中一个作为主要业务对象的基础——并且只将文件以一种方式导入到该州。
如果这两个状态都不是主要业务对象的基础,请引入第三个状态来承担此角色,并将其他状态导入其中。
然后,使用 NGXS 提供的 Meta-Selector,并在那里加入相关的状态。
例如
export class DaysState{
@Selector([DaysState, PlayersState])
static getGameState(days, players) {
return [...days, ...players];
}
}
