ngrx对组件的调度操作(与路由关联)init

时间:2017-09-23 10:30:16

标签: angular ngrx angular-router ngrx-effects

角5+,ngrx 4 +

ARTICLES_LIST_REQUEST初始化与ArticlesListComponent path相关联的/articles时,我尝试做的是触发dispatch

有很多方法可以使用ngOnInit内的dispatch,例如在警卫上使用@ngrx/router-store,但我想要做的是使用{{1听取ROUTER_NAVIGATION并将其映射到ARTICLES_LIST_REQUEST(实际上是ARTICLES_LIST_PARAMS_SET,将当前路线参数保存到商店,但这没关系),现在有几个问题那个。

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

曾经有一种方法可以在组件内暂停/启动/取消订阅/订阅效果,我认为这种方式不再可行,但它会将责任转移回组件,这不会太多比从组件/后卫调度动作更好。

我根本不应该使用router-store吗?

1 个答案:

答案 0 :(得分:1)

这是我最终的结果:

1)为路由定义的name

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

2)为router-store创建一个自定义serializer,每个params只提取queryParamsnamedata.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; } )树上的孩子

let

3)为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)); }; }; 创建一个函数,过滤并映射到名称与您提供的名称相匹配的第一条路线

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

现在我可以这样做

firstChild

这或多或少仅仅是一个概念证明,实际上我不仅要检查第一个孩子,还要检查所有孩子。

我首先只使用树的最后一个id,但有些情况下不起作用,例如,如果您想从这些路线中保存/articles/:id/graph

/articles/:id/table / firstChild,最后一个id,不会包含2 + 4/2 * 3 = 2+2*3 = 2+6 = 8,因此需要找到与该名称匹配的第一个子项并映射到该名称(如果没有找到则过滤)。