我是 ngrx/store 的初学者,这是我第一个使用它的项目。
我已经成功地使用 ngrx/store 设置了我的 Angular 项目,并且在初始化我的主要组件后,我能够调度加载操作,如下所示:
ngOnInit() { this.store.dispatch({type: LOAD_STATISTICS}); }
我已经设置了一个效果来在分派此操作时加载数据:
@Effect() loadStatistic = this.actions.ofType(LOAD_STATISTICS).switchMap(() => { return this.myService.loadStatistics().map(response => { return {type: NEW_STATISTICS, payload: response}; }); });
我的减速器看起来像这样:
reduce(oldstate: Statistics = initialStatistics, action: Action): Statistic { switch (action.type) { case LOAD_STATISTICS: return oldstate; case NEW_STATISTICS: const newstate = new Statistics(action.payload); return newstate; ....
虽然这可行,但我无法理解如何将它与路由器防护一起使用,因为我目前只需要调度 LOAD_ACTION 一次。
此外,一个组件必须调度一个 LOAD 动作来加载初始数据对我来说听起来不正确。我希望商店本身知道它需要加载数据,而我不必先调度动作。如果是这种情况,我可以删除组件中的 ngOnInit() 方法。
我已经研究了 ngrx-example-app 但我还没有真正理解它是如何工作的。
编辑:
添加返回 ngrx-store observable 的解析保护后,路由不会被激活。这是解决方法:
@Injectable() export class StatisticsResolver implements Resolve<Statistic> { resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Statistic> { // return Observable.of(new Statistic()); return this.store.select("statistic").map(statistic => { console.log("stats", statistic); return statistic; }); }
这是路线:
const routes: Routes = [ {path: '', component: TelefonanlageComponent, resolve: {statistic: TelefonieStatisticResolver}}, ];
在 AngularFrance 提供宝贵意见后,我自己解决了这个问题。由于我仍然是初学者,我不知道这是否应该这样做,但它确实有效。
我实现了这样的 CanActivate Guard:
@Injectable() export class TelefonieStatisticGuard implements CanActivate { constructor(private store: Store<AppState>) {} waitForDataToLoad(): Observable<Statistic> { return this.store.select(state => state.statistic) .filter(statistic => statistic && !statistic.empty); } canActivate(route: ActivatedRouteSnapshot): Observable<boolean> { this.store.dispatch({type: LOAD_STATISTIC}); return this.waitForDataToLoad() .switchMap(() => { return Observable.of(true); }); } } }
canActivate(…) 方法首先调度一个动作来加载数据。在 waitForDataToLoad() 中,我们过滤数据已经存在并且不为空(我的业务逻辑的实现细节)。
在这返回 true 之后,我们调用 switchMap 来返回一个为 true 的 Observable。