Angular 5+、ngrx 4+
我想做的是触发ARTICLES_LIST_REQUEST
当ArticlesListComponent
,与 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对于仅提取 params
、queryParams
和 name
的 router-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/