Jor*_*rdi 3 typescript ngrx angular
我试图弄清楚如何在我的ngrx商店中使用“实体数组”进行处理。
我的意思是,我PlanDTO从api服务器上获取了我的收藏。因此,根据我阅读的一些文档,我需要创建某种“表”来存储它们:
export interface IPlan {
id?: string;
name?: string;
...
}
export interface IPlanRedux {
byId: { [key: string]: IPlan };
allIds: Array<string>;
}
Run Code Online (Sandbox Code Playgroud)
因此,在'LOAD_PLANS'调度动作时,也会启动效果:
@Injectable()
export class PlanEffects {
constructor(
private actions$: Actions,
private store$: Store<IStore>,
private planService: PlansService,
) { }
@Effect({ dispatch: true })
loadPlans$: Observable<Action> = this.actions$
.ofType('LOAD_PLANS')
.switchMap((action: Action) =>
this.planService.list()
.map((plans: Array<PlanDTO>) => {
return { type: 'LOAD_PLANS_SUCCESS', payload: plans };
})
.catch((err: ApiError) => {
return Observable.of({ type: 'LOAD_PLANS_FAILED', payload: { code: err.code, msg: err.message } });
})
);
}
Run Code Online (Sandbox Code Playgroud)
如您所见,如果一切都很好,则将“分派”另一个操作:'LOAD_PLANS_SUCCESS'。因此,此操作的简化器是:
private static loadPlansSuccess(plansRdx: IPlanRedux, type, payload: Array<PlanDTO>) {
const plans = payload;
const newPlans = plans.filter(plan => !plansRdx.byId[plan.id]);
const newPlanIds = newPlans.map(plan => plan.id);
const newPlanEntities = plans.reduce((entities: { [id: string]: IPlan }, plan: IPlan) => {
return Object.assign(entities, {
[plan.id]: plan
});
},
{});
return {
ids: [ ...plansRdx.allIds, ...newPlanIds ],
byId: Object.assign({}, plansRdx.byId, newPlanEntities),
};
}
Run Code Online (Sandbox Code Playgroud)
一切似乎都正常,但是,我不太清楚。我认为这里需要了解两个概念。
我主要的头痛是我需要在组件中使用Observable<IPlanRedux>而不是an 来处理Observable<IPlan>。我的意思是,在我的组件中,我想使用IPlans代替带有field allIds或的表ById。
因此,在内部,我要照顾我的IPlanRedux桌子,但另一方面,我想“发出”已删除的计划和已添加的计划。
我不知道我对ID的解释很好。
编辑
我尝试使用选择器:
export interface IPlanRedux {
entities: { [key: string]: IPlan };
ids: Array<string>;
}
export const getPlans = (planRdx: IPlanRedux) => planRdx.entities;
const getPlansState = (state: IStore) => state.plans;
export const getPlanEntities = createSelector(getPlansState, getPlans);
Run Code Online (Sandbox Code Playgroud)
进入我的组件:
this.plans$ = this.store$.select(fromRoot.getPlanEntities)
.map(plan => {
if (plan.id != null)
Run Code Online (Sandbox Code Playgroud)
首先:“规则和概念”只是应该帮助您找到适合您的应用程序的解决方案的指南-我不知道有人能绝对实现所有这些规则。每个应用程序都是个别的,没有“一刀切”的解决方案。
因此,仅因为有人告诉您使用类似表的结构,并不意味着这是解决您问题的最佳解决方案(另一方面,这也不意味着这将是一个糟糕的解决方案)-您是唯一知道数据和要求的人,您可能是唯一能够做出判断的人-因此,不要盲目相信某些规则,并希望不会有任何不利之处。
至于您的问题:
1.内部表为了存储redux结构。
redux-store或ngrx-store通常与不可变对象结合使用(这使更改检测的性能更好)-在这种情况下,以平面结构而不是嵌套结构管理数据要容易得多,因为在平面(表)结构中,您最多只需重新创建2个级别的数据。但是,当对象具有深层嵌套时,在执行数据突变时必须重新创建更多层数据(取决于嵌套深度)。
因此:当您不使用不可变对象时,您将不会真正从一个或另一个数据结构中受益。(我在这里没有提出任何建议,这是一个技术决定,具体取决于您,个人而言,我喜欢使用不可变对象,但我并非以此为出发点)
2.前端组件
同样,这里有一些“规则”,例如“智能和哑巴组件”,“选择语句与让函数”等。-再说一次:没有真正完美的,万能的解决方案。
至于Observable<IPlanRedux>-您不必到处都做-如果您不满意let函数,则可以在其中创建一些服务类并实现一些简单的select语句:
class StoreService {
iPlans$ = this.store.select(state => state.planRedux)
.map(planRedux => planRedux.allIds.map(id => planRedux.byId[id]));
}
Run Code Online (Sandbox Code Playgroud)
一些个人建议,具体取决于您的情况:
如果您是出于兴趣和学习目的来做这个项目,请:发疯,尽可能多地尝试并尽可能多地学习,尽可能多地休息。-您将遇到挫折,在学习时需要进行重构,但这是值得的。NGRX和redux模式通常是一个非常不错的工具,但是很难缠住您的头,特别是如果您习惯于其他模式。
如果您是为客户进行此项目并作为可用于生产的应用程序:坚持使用您已经知道或接受的事实,如果这是您的第一个ngrx和/或angular2项目,那么在质量和时间上将不可避免地产生后果。 (除非你是个疯狂的天才;-)。
| 归档时间: |
|
| 查看次数: |
838 次 |
| 最近记录: |