2017-09-23 30 views
1

角5+,NGRX 4+NGRX调度组份(与路由相关联)的动作初始化

我试图做的是触发ARTICLES_LIST_REQUESTArticlesListComponent,与path/articles相关被初始化。

有办法做到这一点过多,使用dispatchngOnInit,在例如保护使用dispatch,但我想要做的反而是使用@ngrx/router-store,听ROUTER_NAVIGATION并将其映射到ARTICLES_LIST_REQUEST(实际上ARTICLES_LIST_PARAMS_SET,将当前的路线参数保存到商店中,但这并不重要),现在出现了一些问题。

由于效果,即使是那些注册了forFeature的效果,如果我在多个模块(文章,人物,品牌等)中设置了听ROUTER_NAVIGATION的效果,它会运行多次,触发所有行动,所以我需要一种方法来过滤它只为我感兴趣的路线..但如何?由于在角度路由器中没有命名路由,并且导航操作返回整棵树的快照,因此无法知道刚刚激活的特定路由。我现在在做的是检查并通过网址进行过滤,例如,是否以/articles开头,下一个字符是否不是/(要过滤掉/articles/<id>。但我真的不喜欢它,并不真正感受像它会安全地覆盖所有的情况

曾经有一种方法可以暂停/启动/取消订阅/订阅组件内的效果,我认为这不再是真的可能,但它会移动责任回到组件,这不会比从组件/防护装置调度动作好得多。

我应该不是使用router-store吗?

回答

1

这是我结束了:

1)添加了独特name路由定义的data

export const ROUTES: Routes = [ 
    { 
    path: '/articles', 
    component: ArticlesListPage, 
    data: { 
     name: 'articles-list' 
    } 
    } 
]; 

2)创建一个自定义serializerrouter-store只提取paramsqueryParamsname(从data.name )树中的每个孩子

function createSerializedTree(node: ActivatedRouteSnapshot) { 
    const tree = { 
    queryParams: node.queryParams, 
    params: node.params, 
    name: node.data.name, 
    children: node.children.map(createSerializedTree), 
    firstChild: undefined 
    }; 

    tree.firstChild = tree.children[0]; 

    return tree; 
} 

3)创建一个函数f该过滤器和地图与名称的第一个路径匹配一个你提供

const _checkIsNodeHasName = (name: string, node: SerializedRouterNode) => { 
    if (node.name === name) { 
    return node; 
    } else if (node.firstChild) { 
    return _checkIsNodeHasName(name, node.firstChild); 
    } else { 
    return undefined; 
    } 
} 

export const filterAndMapRoute = (name: string) => { 
    return (navigationAction$: Observable<RouterNavigationAction<RouterStateUrl>>) => { 
    return navigationAction$ 
     .map(action => action.payload.routerState) 
     .filter((state) => !!_checkIsNodeHasName(name, state.root)) 
     .map((state) => _checkIsNodeHasName(name, state.root)); 
    }; 
}; 

let现在我能做到这一点

@Injectable() 
export class ArticlesEffects { 
    @Effect() 
    private _onRouteChange$ = this._action$ 
    .ofType(ROUTER_NAVIGATION) 
    .let(filterAndMapRoute('posts-list')) 
    .map(/* ... */) // map to whatever action I need 
} 

这或多或少只是一个概念证明,现实我会不仅需要检查firstChild,还要检查所有的孩子。

我先用简单的树的最后firstChild去了,但有些情况下,如果你想救id从这些途径

/articles/:id/graph//articles/:id/table,最后firstChild那就没办法了,例如情况下,将不包含id,因此需要找到与名称匹配的第一个孩子并映射到该孩子(如果没有找到,则进行筛选)。