angular - ngrx 在组件(与路由关联)init 上调度操作

标签 angular ngrx angular-router ngrx-effects

Angular 5+、ngrx 4+

我想做的是触发ARTICLES_LIST_REQUESTArticlesListComponent ,与 path 关联/articles已初始化。

有很多方法可以做到这一点,使用 dispatch里面ngOnInit ,使用dispatch例如,在 guard 身上,但我想做的是使用 @ngrx/router-store ,听ROUTER_NAVIGATION并将其映射到 ARTICLES_LIST_REQUEST (实际上 ARTICLES_LIST_PARAMS_SET ,将当前路由参数保存到存储中,但这并不重要),现在存在一些问题。

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

曾经有一种方法可以在组件内暂停/启动/取消订阅/订阅效果,我认为这不再可能了,但它将把责任移回组件,这不会太多比从组件/防护中分派(dispatch)操作更好。

我不应该使用 router-store到底是为了这个?

最佳答案

这就是我最终得到的结果:

1) 添加唯一的名称到路由定义的数据

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

2) 创建自定义serializer对于仅提取 paramsqueryParamsnamerouter-store (来自 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) 为 let 创建一个函数,用于过滤并映射到名称与您提供的匹配的第一个路由

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
}

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

我首先使用树的最后一个 firstChild ,但在某些情况下这不起作用,例如,如果您想从这些中保存 id路线

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

关于angular - ngrx 在组件(与路由关联)init 上调度操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46378605/

相关文章:

Angular 路由有多个参数,有的在中间

angular - 在新的 Angular 2 表单中将 NgModel 绑定(bind)到 FormControl

angular - 获取 Firebase Firestore 集合中最后创建的文档

python - Angular 服务正常工作,Angular 构建不更新文件

angular - 如何使用@ngrx/store 获取 State 对象的当前值?

angular - ngrx:提供的参数与调用目标的任何签名都不匹配

angular - 使用 ngrx 从 Effect 访问 store

angular - Protractor 无法找到元素并且脚本超时

css - 具有多个路由器 socket 的 Angular 7 路由器动画

Angular 9 Router - CanActivate 不适用于重定向