问题描述:
我经常重复使用常见的UI元素,例如“Datatable”:
每当向此表添加功能时,我们必须在每个模块中单独添加功能,从而导致大量浪费的工作和代码重复。
解决方案提案:
我想创建这个表的单个有状态实现作为ngModule,这样当我们调整表的核心行为(例如添加一个特性)时,我们只需进行更改在一个地方。
事实证明,实施这一点很困难。我似乎无法解决的主要问题是dataTable的多个实例意味着当一个实例调度一个新操作时,每个实例都会在其各自的reducer中处理它。
为了解决这个问题,我实施了以下脚手架:
Store
→ featureA
→ dataTable
→ featureB
→ dataTable
然后在dataTable组件的ngOnInit()函数中,我使用带有标识符的“forFeature”有效负载调度“InitTable”操作,以指定操作所针对的功能。
然后在featureA& B,我有一个效果,它使用与其标识符匹配的forFeature属性侦听InitTable Action,然后调度“特定于功能”的操作。这看似合适
@Effect()
tableInit$: Observable<Action> = this.actions$.pipe(
filter((x: Action) => x['forFeature'] && x['forFeature'] === 'A'), // ‘A’ as id
ofType(<string>DataTableActionTypes.InitTable),
map((action: Action) => {
return new InitATable(); // Action specified at the ‘feature’ level
})
);
然后,此功能应由功能级别的reducer捕获,并调整其子dataTable状态的字段。我似乎无法让这部分工作,我想知道它是否违反了试图在父级调整孩子状态的模式?下面是我想象的代码的粗略估计:
export function aReducer(state, action) {
switch(action.type){
case AActionTypes.InitATable: {
return { ...state, dataTable: { ...state.dataTable, feature: ‘A’ } }
}
....
} }
在此之后,在dataTable的reducer内部,在输入典型的switch语句之前,如果dataTable是动作的forFeature属性中的标识符不等于dataTable状态的'feature'字段所包含的标识符,则返回原始状态
export function dataTableReducer(state, action) {
if(action.forFeature !== state.feature){
return state;
}
switch(action.type){
case AActionTypes.InitATable: {
return { ...state, dataTable: { ...state.dataTable, feature: ‘A’ } }
}
....
} }
我相信这应该有用,只要我找到一种方法来单独设置不同dataTables的'feature'值。
更新:与我最初的想法相反,黑客攻击和调试表明问题不在于有不同的dataTable实例,每个实例都听取了针对其他datraTable的操作,但每个不同的引用都是针对子dataTable的事实指向同一个实例。