我们正在将Angular 7与NGRX结合使用来开发SPA。几个月前,我们已经迁移到NGRX,主要用于身份验证和会话数据。之后,我们也开始移动其他功能。我将描述这个问题以及我们头脑中有什么解决方案及其弊端。得知您如何解决此问题(如果有)或解决问题的想法,我将非常感激。
ChangeDetectionStrategy.OnPush
时Angular的执行速度显着在我们的应用程序中,我们有6个模块。每个模块至少具有10个功能(页面)。我们之间只有很少的共同细节。
由于我们的主要问题是#1和#2(如上所述),所以我们从以下商店结构开始:
{
"authentication": {
"isLoading": false,
"error": {},
"token": "auth-token"
},
"session": {
"userDetailsIsLoading": false,
"userDetailsData": {},
"userDetailsError": {}
}
}
到目前为止,太好了。就像所有带有增加/减少/重置计数器的Redux教程一样。
这是有趣的开始,因为我们在应用程序内部有很多功能(6个模块* 10个功能= 60+)。
第一个决定是使用reducer per feature
而不是reducer per entity
,因为我们拥有的页面具有相同的实体类型,但是使用不同的过滤器获取。由于大量数据,我们正在服务器端过滤数据。
例如:最近10篇帖子,前10篇帖子-都在同一页面上
因此,我们扩大了我们的商店,增加了更多的减速器:
{
"authentication": {},
"session": {},
"blogs-list": {},
"blogs-add": {},
"administration-users": {},
"administration-add-user": {}
}
是的,我们使用格式[Feature] Action Description
时遇到了第一类碰撞。
为了解决这个问题,我们决定添加使用命名空间[Module][Feature] Action Description
。
那是最大的问题。整个商店变得很大。商店干净时这不是问题,但是经过几次导航后,商店中包含许多不需要的数据。
Angular允许延迟加载所谓的NGRX Features
。这意味着我们可以仅从共享数据(身份验证,会话)开始,一旦打开模块,所有的reducer都将添加到存储中。该解决方案部分地解决了该问题。如果您导航到所有模块,那么商店将再次变大。
从理论上看这很容易,但是在实践中却很难。正如我提到的,我们有一种仪表板,其中显示相同的实体,但使用不同的过滤器和分页获取。在头脑中,我有一个想法针对这些情况使用不同的减速器,例如:
{
"latest-entities": {
"isLoading": bool,
"data": {},
"error": {},
},
"most-popular-entities": {
"isLoading": bool,
"data": {},
"error": {},
}
}
但是这里还有另一个缺点。我们曾经将过滤器保留在功能存储中,并且一旦我们更改过滤器,效果就会触发数据重新加载。切换到此体系结构,我们将数据重新加载的责任移至containers
。 Container
将负责向商店latest-entities
和most-popular-entities
分发动作。这个解决方案也将越来越大。通过重组reduces和store无法完全解决该问题。
我们可以将功能逻辑保留在containers
中,并将redux仅用于跨模块数据,例如会话,身份验证和通知。这也是一种解决方案,但有其缺点。我想保持应用程序的一致性,并且不要在容器和存储中都包含业务逻辑。
为使商店变小,我们可以创建一个操作,将商店重置为初始状态,一旦不使用该功能便将分派该商店。这是一个示例:
public ngOnDestroy(): void {
this.store$.dispatch(new BlogStoreActions.DestroyAction());
}
答案 0 :(得分:1)
我无法发表评论,但是您的问题让我感到好奇,因此我将其提交给了Twitter和ngrx维护者之一。
以下是回应(来自Wes Grimes):
如果商店太大,那么也许是时候重新考虑从客户端获取什么数据了。您真的是完整的数据模型还是配对的向下视图模型就足够了?一次批量获取数据。获得50,然后根据需要再返回50(延迟加载)。
还可以利用角度中的延迟加载特征模块,将forFeature与NgRx结合使用,然后仅加载所需的部分存储。但是再说一次。如果需要考虑大小,请考虑最小化客户端数据并将繁重的工作转移到后端。
链接: