我有这个减速器
on(CmsActions.loadCmsTopNewsSelected, (state, { slug }) => { let selected; if (state.data) { selected = state.data.items.find(item => item.data.slug.iv === slug); } return { ...state, selected }; })
和这个后卫
canActivate(route: ActivatedRouteSnapshot): Observable<boolean | UrlTree> { return this.checkStore().pipe( switchMap(() => { const slug = route.params.slug; this.facade.selected(slug); return this.facade.selected$.pipe( map(selected => { console.log('selected', selected); if (selected) { return true; } return this.router.parseUrl('/not-found'); }) ); }), catchError(() => of(false)) ); } checkStore(): Observable<boolean> { return this.facade.loaded$.pipe( tap(loaded => { if (!loaded) { this.facade.load(this.ITEMS_TO_LOAD); } }), filter(loaded => { console.log('loaded', loaded); return loaded; }), take(1) ); }
如果我通过路由器链接转到路线,效果很好,
但是如果我直接去,则所选择的是不确定的,即使
数据已加载。
怎么了?
为了更好的理解,我发布了更多代码顺便说一句,我正在等待加载数据当子路由正在由浏览器运行时。
路线父母
{ path: 'news', canLoad: [CmsNewsGuard], loadChildren: () => import('./news/news.module').then(m => m.PublicNewsModule) },
儿童
{ path: ':slug', canActivate: [CmsNewsGuardSelected], component: PublicNewsPageDetailsComponent }, { path: '', component: PublicNewsListComponent, pathMatch: 'full' }
外观
export class CmsNewsFacade { get data$(): Observable<CmsArray<CmsNews> | null> { return this.store.pipe(select(selectCmsNewsData)); } get error$(): Observable<Required<ErrorDto> | null> { return this.store.pipe(select(selectCmsNewsError)); } get loaded$(): Observable<boolean> { return this.store.pipe(select(selectCmsNewsLoaded)); } get selected$(): Observable<CmsNews | undefined> { return this.store.pipe(select(selectCmsNewsSelected)); } constructor(private store: Store<CmsState>) {} load(top: number): void { this.store.dispatch(CmsActions.loadCmsTopNews({ top })); } selected(slug: string): void { this.store.dispatch(CmsActions.loadCmsTopNewsSelected({ slug })); } }
选择器
export const selectCmsNewsSelected = createSelector( selectMarketAccountFeature, (state: CmsState) => { return state.news.selected; } );
UPDATE2
它起作用
return this.facade.selected$.pipe( filter(selected => { return !!selected; }), map(selected => { if (selected) { return true; } return this.router.parseUrl('/not-found'); }) );
但是这样做我失去了目标,显示未找到的页面如果子弹不存在:(
我已经在(CmsActions.loadCmsTopNewsSelected,(state,{slug})=> { .slug.iv === ...
我认为您的选择器会尝试选择一个未定义的状态,因为加载页面时,Guard会比加载后存储在存储中的数据外观更快地检查条件。这是因为延迟加载。预先加载的模块中提供了您的Guard。您的商店商品是在延迟加载的模块中声明的,这就是为什么您的Guard在第一次加载时不接受导航的问题。