首页 > 解决方案 > ngrx:在加载页面之前从商店获取价值

问题描述

我有页面组件,在里面我显示了一些数据ngrx/store

// profile.ts
user$: User = this.store.select('user')
// profile.html
...

<div *ngIf="user$ | async; let user">
  <div>{{user.id}}</div>  
  <div>{{user.email}}</div>
</div>

这可行,但我不喜欢它最初加载没有数据的页面,然后在 1 秒后从user$. 我知道这是应该的 - 因为我使用的是异步管道,但我想改变它。

我有什么选择?我能否以某种方式user从商店中预加载此选择,以便将其包含在所有组件中,这样我就不需要每次都从商店中请求它们,因此,我从商店中获取一些数据的所有页面“闪烁” ” 加载后?

标签: angularngrxngrx-store

解决方案


如果数据已经在商店中,那么不获取数据的最简单方法是在效果内 -自己开始为此使用 ngrx/effects

@Effect()
getOrder = this.actions.pipe(
  ofType<GetOrder>(ActionTypes.GetOrder),
  withLatestFrom(action =>
    of(action).pipe(
      this.store.pipe(select(getOrders))
    )
  ),
  filter(([{payload}, orders]) => !!orders[payload.orderId])
  mergeMap([{payload}] => {
    ...
  })
)

但我认为您正在寻找的是 Angular 路由器保护,以便在您的商店中有数据后获取数据并加载页面。有关更多信息,请参阅Todd Motto 的使用 Route Guards 预加载 ngrx 商店。

@Injectable()
export class CoursesGuard implements CanActivate {
  constructor(private store: Store<CoursesState>) {}

  getFromStoreOrAPI(): Observable<any> {
    return this.store
      .select(getCoursesState)
      .do((data: any) => {
        if (!data.courses.length) {
          this.store.dispatch(new Courses.CoursesGet());
        }
      })
      .filter((data: any) => data.courses.length)
      .take(1);
  }

  canActivate(): Observable<boolean> {
    return this.getFromStoreOrAPI()
      .switchMap(() => of(true))
      .catch(() => of(false));
  }
}

对于(最好的?)用户体验,您还可以使用 Ghost 元素 - Thomas Burleson的 Ghost Elements 的出色用户体验。


推荐阅读