我正在使用ngrx/store
和Angular 6
。我在商店中有很深的嵌套结构。但是我觉得保持这样的方法不正确:
const state = [
{
aliases: ['alias1', 'alias2'],
isRequired: false,
isSensitive: false,
name: 'Adress',
timezoneId: 'UTC',
children: []
},
{
aliases: ['alias3', 'alias4'],
isRequired: true,
isSensitive: false,
name: 'Phone',
timezoneId: 'UTC-5',
children: [
{
aliases: ['alias1', 'alias2'],
isRequired: true,
isSensitive: false,
name: 'Sub-Phone',
timezoneId: 'UTC-5',
children: [
{
aliases: ['alias-phone1', 'alias-phone2'],
isRequired: false,
isSensitive: true,
name: 'Sub-Sub-Phone',
timezoneId: 'UTC',
children: []
}
]
}
]
}
]
此处的属性name
类似于id
,在同一级别上不能相同,但在子级中可以相同。例如,Sub-Phone
和Sub-Sub-Phone
可以命名为Phone
。在商店中保留此类易于更改的结构的最佳方法是什么。因为现在如果要更改name: 'Phone'
,我应该将其所有子级对象全部归还到reducer中。我如何将其标准化?
通常的模式是跟随this guide,以标准化状态形状。不要筑巢。创建一个存储实体的ID。然后创建一个存储关系的ID(在您的方案中为孩子)。我为您建立了一个示例状态
const state = {
objects: {
id: ['Address', 'Phone', 'Sub-Phone', 'Sub-Sub-Phone'],
entities: {
'Address': {
isRequired: false,
isSensitive: false,
timezoneId: 'UTC'
},
'Phone': {
isRequired: true,
isSensitive: false,
timezoneId: 'UTC-5'
},
'Sub-Phone': {
isRequired: true,
isSensitive: false,
timezoneId: 'UTC-5',
},
'Sub-Sub-Phone': {
isRequired: false,
isSensitive: true,
timezoneId: 'UTC',
}
}
},
children: {
'Address': [],
'Phone': ['Sub-Phone'],
'Sub-Phone': ['Sub-Sub-Phone']
}
}
请注意,状态有2个级别:一个用于对象,一个用于子级。 objects
存储ID和实体。子项将每个对象键及其子项存储一个数组。请注意,在ny示例中,数组中只有一个子级,但是您可以使用类似
'Phone': '['Sub-Phone', 'Sub-Phone2', 'Sub-Phone3']
@ ngrx / entity是规范商店的一种非常简洁的方法。看看这个@ngrx/entity ReadMe。
此外,它还具有强大的实体适配器和选择器。
如果您有权访问服务器实现,则可以直接在此处进行规范化。但是,您更有可能使用第三方库(例如normalizr)来规范客户端中的状态。
[有几篇文章讨论了这个主题,例如this one on Hackernoon。