代码之家  ›  专栏  ›  技术社区  ›  Wayne Riesterer

角6、NGXS和消防站

  •  2
  • Wayne Riesterer  · 技术社区  · 6 年前

    我有一个firestore数据库,它的集合排列类似于相关集合中的关系数据库,存储外键。做出此决定是为了使与现有.NET服务的集成更容易,并允许更大的灵活性。

    以下是数据模型的一部分:

    我已经将我的状态划分为功能模块,并有如下代码:

    ngxsoninit(ctx:stateContext<schedulesstatemodel>){
    调度()
    新建getscheduleGroups(),
    新建GetSchedules()
    )
    }
    
    @选择()
    静态计划组(状态:schedulesstatemodel):数组<schedulegroup>。{
    返回state.schedulegroups;
    }
    
    @选择()
    静态scheduleGroupByID(状态:schedulesstatemodel){
    返回(scheduleGroupID:string)=>。{
    return state.scheduleGroups.filter((scheduleGroup:scheduleGroup)=>
    scheduleGroup.id==scheduleGroupID);
    };
    }
    
    @操作(GetScheduleGroups)
    getscheduleGroups(patchState:StateContext<schedulesstatemodel>){
    返回此.dataservice.getdocuments$<schedulegroup>('schedulegroups')
    .pipe(tap(schedulegroups=>patchState(schedulegroups));
    }
    
    @操作(GetSchedules)
    获取计划(patchState:StateContext<schedulesstatemodel>){
    返回此.dataservice.getdocuments$<schedule>('schedules')
    .pipe(tap(schedules=>patchstate(schedules));
    }
    < /代码> 
    
    

    在scheduleList组件中,我有以下代码:

    getschedulesbyid$(schedulegroupid:string){
    返回此.store.select(schedulesstate.schedulesByGroupID)
    .pipe(映射(schedulesfilter=>schedulesfilter(schedulegroupid));
    }
    < /代码> 
    
    

    我可以将getschedulesbyid$的检索逻辑移到state类中,但是我现在对代码进行结构化的方式,需要一种为每个schedulegroup检索计划的方法;因为schedulegroup是迭代的,每个组的计划是检索来显示的。这可以在以下模板片段中看到:

    <ngb选项卡
    *ngfor=“让schedulegroup of(getschedulegroups$(schedulegroupcollection.id)async)”
    [标题]=“scheduleGroup.name”>
    <ng模板ngbtabcontent>
    <div class=“schedules container”[ngStyle]=“height:tabheight”>
    <IBMS计划列表项
    *ngfor=“让调度(getschedules$(scheduleGroup.id)async)”
    [schedule]=“时间表”>
    </ibms计划列表项>
    &L/DIV & GT;
    </ng模板
    </ngb选项卡>
    < /代码> 
    
    

    这段代码可以工作,但看起来很冗长。有更好的方法吗?

    我遇到的一个问题是,即使是简单的组件最终也会变成容器。以scheduleList组件为例,它需要显示相关表中的数据。获取此数据取决于在*ngfor迭代期间哪个特定计划项处于焦点。

    有什么改进的建议吗?我几乎可以肯定有更好的方法,但我不确定它是什么。

    另外,这里是数据服务:

    import injectable from'@angular/core';
    从'RXJS'导入可观察;
    从“RXJS/内部兼容性”导入FromPromise;
    从“rxjs/operators”导入map;
    
    从“angularfire2/firestore”导入angularfirestore;
    导入wherefilterop=firebase.firestore.wherefilterop;
    
    从“guid typescript”导入guid;
    
    可注射的({)
    providedIn:'根'
    })
    导出类DataService{
    
    建设者(私有数据库:angularfirestore)
    
    getdocuments$<t>(collectionname:string):可观察的{
    返回此.db.collection<t>(collectionname).snapshotchanges().pipe(
    映射(actions=>actions.map(action=>){
    const id=action.payload.doc.id;
    const data:t=action.payload.doc.data()作为t;
    数据['id']=id;
    返回<t>数据;
    })
    ;
    }
    
    GetDocumentsByQuery$<t>(集合名称:字符串,属性名称:字符串,
    ComparisonOperator:WhereFilterOp,TargetValue:String_Boolean):可观察{
    返回此.db.集合<t>。(
    集合名
    ref=>ref.where(propertyname、comparisonoperator、targetValue)).snapshotchanges().pipe(
    映射(actions=>actions.map(action=>){
    const id=action.payload.doc.id;
    const data:t=action.payload.doc.data()作为t;
    数据['id']=id;
    返回数据;
    })
    ;
    }
    
    adddocument<t>(集合名称:字符串,文档:t){
    const-guid:string=guid.raw();
    从Promise返回(this.db.collection<t>(collectionname).doc(guid).set(document)
    管子(
    图(())=gt;{
    const返回文件:t=文件;
    文档['id']=guid;
    退货单;
    })
    ;
    }
    
    addbatch<t>(集合名称:字符串,文档:数组<t>){
    const batch=this.db.firestore.batch();
    const collectionref=this.db.collection<t>(collectionname);
    
    documents.foreach((document:t)=>。{
    const-guid:string=guid.raw();
    const doc ref=collectionref.doc(guid.ref);
    批处理集(docref,document);
    (});
    
    从Promise返回(batch.commit());
    }
    
    updateDocument<t>(collectionName:string,document:t,data:any){
    返回此.db.collection<t>(collectionname).doc(document['id']).update(data);
    }
    
    删除文档<t>(集合名称:字符串,文档:t){
    返回此.db.collection<t>(collectionname).doc(document['id']).delete();
    }
    
    }
    < /代码> 
    
    

    我知道这项服务可以改进,我会做好准备,但我认为为了完整起见,我会将其包括在内。

    如有任何改进建议,我们将不胜感激。

    以下是数据模型的一部分:

    enter image description here

    我已经将我的状态划分为功能模块,并有如下代码:

      ngxsOnInit(ctx: StateContext<SchedulesStateModel>) {
        ctx.dispatch([
          new GetScheduleGroups(),
          new GetSchedules()
        ]);
      }
    
      @Selector()
      static scheduleGroups(state: SchedulesStateModel): Array<ScheduleGroup> {
        return state.scheduleGroups;
      }
    
      @Selector()
      static scheduleGroupById(state: SchedulesStateModel) {
        return (scheduleGroupId: string) => {
          return state.scheduleGroups.filter((scheduleGroup: ScheduleGroup) =>
            scheduleGroup.id === scheduleGroupId);
        };
      }
    
      @Action(GetScheduleGroups)
      getScheduleGroups({ patchState }: StateContext<SchedulesStateModel>) {
        return this.dataService.getDocuments$<ScheduleGroup>('scheduleGroups')
          .pipe(tap(scheduleGroups => patchState({ scheduleGroups })));
      }
    
      @Action(GetSchedules)
      getSchedules({ patchState }: StateContext<SchedulesStateModel>) {
        return this.dataService.getDocuments$<Schedule>('schedules')
          .pipe(tap(schedules => patchState({ schedules })));
      }
    

    在scheduleList组件中,我有以下代码:

      getSchedulesById$(scheduleGroupId: string) {
        return this.store.select(SchedulesState.schedulesByGroupId)
          .pipe(map(schedulesFilter => schedulesFilter(scheduleGroupId)));
      }
    

    我可以将getschedulesbyid$的检索逻辑移到state类中,但是我现在对代码进行结构化的方式,需要一种为每个schedulegroup检索计划的方法;因为schedulegroup是迭代的,并且为显示而检索每个组的计划。这可以在以下模板片段中看到:

    <ngb-tab
      *ngFor="let scheduleGroup of (getScheduleGroups$(scheduleGroupCollection.id) | async)"
      [title]="scheduleGroup.name">
      <ng-template ngbTabContent>
        <div class="schedules-container" [ngStyle]="{ height: tabHeight }">
          <ibms-schedules-list-item
            *ngFor="let schedule of (getSchedules$(scheduleGroup.id) | async)"
            [schedule]="schedule">
          </ibms-schedules-list-item>
        </div>
      </ng-template>
    </ngb-tab>
    

    这段代码可以工作,但看起来很冗长。有更好的方法吗?

    我遇到的一个问题是,即使是简单的组件最终也会变成容器。以scheduleList组件为例,它需要显示相关表中的数据。获取此数据取决于在*ngfor迭代期间重点关注的特定计划项。

    有什么改进的建议吗?我几乎可以肯定有更好的方法,但我不确定它是什么。

    此外,这里还有数据服务:

    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs';
    import { fromPromise } from 'rxjs/internal-compatibility';
    import { map } from 'rxjs/operators';
    
    import { AngularFirestore } from 'angularfire2/firestore';
    import WhereFilterOp = firebase.firestore.WhereFilterOp;
    
    import { Guid } from 'guid-typescript';
    
    @Injectable({
      providedIn: 'root'
    })
    export class DataService {
    
      constructor(private db: AngularFirestore) {}
    
      getDocuments$<T>(collectionName: string): Observable<T[]> {
        return this.db.collection<T>(collectionName).snapshotChanges().pipe(
          map(actions => actions.map(action => {
            const id = action.payload.doc.id;
            const data: T = action.payload.doc.data() as T;
            data[ 'id' ] = id;
            return <T>data;
          }))
        );
      }
    
      getDocumentsByQuery$<T>(collectionName: string, propertyName: string,
                              comparisonOperator: WhereFilterOp, targetValue: string | boolean): Observable<T[]> {
        return this.db.collection<T>(
          collectionName,
          ref => ref.where(propertyName, comparisonOperator, targetValue)).snapshotChanges().pipe(
          map(actions => actions.map(action => {
            const id = action.payload.doc.id;
            const data: T = action.payload.doc.data() as T;
            data[ 'id' ] = id;
            return data;
          }))
        );
      }
    
      addDocument<T>(collectionName: string, document: T) {
        const guid: string = Guid.raw();
        return fromPromise(this.db.collection<T>(collectionName).doc(guid).set(document))
          .pipe(
            map(() => {
              const returnDocument: T = document;
              document[ 'id' ] = guid;
              return returnDocument;
            })
          );
      }
    
      addBatch<T>(collectionName: string, documents: Array<T>) {
        const batch = this.db.firestore.batch();
        const collectionRef = this.db.collection<T>(collectionName);
    
        documents.forEach((document: T) => {
          const guid: string = Guid.raw();
          const docRef = collectionRef.doc(guid).ref;
          batch.set(docRef, document);
        });
    
        return fromPromise(batch.commit());
      }
    
      updateDocument<T>(collectionName: string, document: T, data: any) {
        return this.db.collection<T>(collectionName).doc(document['id']).update(data);
      }
    
      deleteDocument<T>(collectionName: string, document: T) {
        return this.db.collection<T>(collectionName).doc(document['id']).delete();
      }
    
    }
    

    我知道这个服务可以改进,我将着手做这件事,但我认为为了完整性,我会将它包括进来。

    任何改进的建议都会受到赞赏。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Garth Mason    6 年前

    一些值得考虑的建议:

    由于日程表总是在一个组中使用,因此 @Selector 它投射出这种结构。

    它仍然可以是一个动态选择器,参数为 scheduleGroupId ,而不是只返回组,而是返回包含其子集合的组 schedules . 那么在模板中,您只有一个 Observable 它返回所需数据的形状。该投影可能更适合于UI,而如果您稍后通过日程表上的CRUD操作修补该状态,那么保持一个平面结构可能会使您的生活更轻松?

    我遇到的一个问题是,即使是简单的组件最终也会变成容器。以scheduleList组件为例,它需要显示相关表中的数据。获取此数据取决于在*ngfor迭代期间重点关注的特定计划项。

    我不太清楚你所说的这是什么意思,因为你要把行动分派给 GetSchedules GetScheduleGroups 通过ngxs初始化钩子,你将得到所有的东西,不管怎样,都是热切的,对吗?我可能误解了一些事情。

    正在使用组件 SchedulesListItem 导致问题?