Angular 9-解析给定url的每个参数

Angular 9-解析给定url的每个参数,angular,url,angular-routing,angular9,urlparse,Angular,Url,Angular Routing,Angular9,Urlparse,假设我们有以下几种URL: [1]/home/users/:id [2]/home/users/:id/posts/:id [3]/code>/home/users/:id/posts/:id/comments/:id 我想创建一个方法parseUrl(url:string):任何[]{},它接受一个url并返回一个包含该url的每个参数的数组。因此,parseUrl('/home/users/:id/posts/:id/comments/:id')将导致[userId,postId,comme

假设我们有以下几种URL:

[1]
/home/users/:id

[2]
/home/users/:id/posts/:id

[3]/code>/home/users/:id/posts/:id/comments/:id

我想创建一个方法parseUrl(url:string):任何[]{},它接受一个url并返回一个包含该url的每个参数的数组。因此,
parseUrl('/home/users/:id/posts/:id/comments/:id')
将导致
[userId,postId,commentId]
我如何实现这一点

天真的方法: 假设我们知道哪些url段可以包含参数(在本例中为用户、帖子和评论),我们可以通过
'/'
字符分割url,检查该段是否等于用户、帖子或评论,最后将后续段作为url

parseUrl(url: string): any[] {
    let params = new Array<any>();
    url.split('/')
      .filter((segment, index, urlSegments) => index > 0 && ['users', 'posts', 'comments'].includes(urlSegments[index - 1]))
      .forEach(segment => params.push(segment))
    return params;
}
将生成一个对象,该对象仅包含
{'id':5}
/home/users/10/posts/10/comments/5
作为当前url。这是因为(至少我认为)我已经为用户、帖子和评论配置了延迟加载模块。因此,我有3个路由模块,一个匹配路由
users/:id
,第二个匹配
posts/:id
,第三个匹配
comments/:id
。我发现ActivatedRouteSnapshot将它们视为3个单独的url段,每个url段有一个参数,而不是一个单独的url段有3个参数

因此,最后,是否有一种编程和通用的方法可以从Anuglar 9中的url获取每个参数?

除了使用“必需”的路由参数外,您还可以使用可选的参数通过路由发送对象

试试下面的方法

路径配置

{path:'/home/users/',组件:UsersComponent}
呼叫路线

。。。

this.router.navigate(['/home/users',{data:JSON.stringify([userId,postId,commentId]));
结果URL

http://myapp.com/home/users;data=...
检索数据

JSON.parse(this.router.snapshot.paramMap.get('data');
不使用“必需”路由参数,您可以使用可选参数通过路由发送对象

试试下面的方法

路径配置

{path:'/home/users/',组件:UsersComponent}
呼叫路线

。。。

this.router.navigate(['/home/users',{data:JSON.stringify([userId,postId,commentId]));
结果URL

http://myapp.com/home/users;data=...
检索数据

JSON.parse(this.router.snapshot.paramMap.get('data');

您需要递归地遍历路由器树以收集所有参数。 此代码段仅适用于参数键唯一的情况,因此

/home/users/:id/posts/:id/comments/:id
必须是
/home/users/:userId/posts/:postd/comments/:commentId
。如果希望保留旧的paramkey名称,则需要相应地修改代码段

它可能是这样的:

export parseUrl(route: ActivatedRouteSnapshot): Map<string,string> {
  const result = reduceRouterChildrenParams(route.root.firstChild, new Map<string, string>());
  return result;
}

reduceRouterChildrenParams(routerChild: ActivatedRouteSnapshot | null, data: Map<string, string>): RouteWalkerResult {
  if (!routerChild) {
      return data;
  }
  for (const paramMapKey of routerChild.paramMap.keys) {
    data.set(paramMapKey, routerChild.paramMap.get(paramMapKey)!);
  }
  return routerChild.children.reduce((previousValue, currentValue) => {
    return reduceRouterChildrenParams(currentValue, previousValue);
  }, data);
}
导出解析URL(路由:ActivatedRouteSnapshot):映射{ const result=reduceRouterChildrenParams(route.root.firstChild,new Map()); 返回结果; } reduceRouterChildrenParams(routerChild:ActivatedRouteSnapshot | null,数据:Map):RouteWalkerResult{ 如果(!routerChild){ 返回数据; } for(routerChild.paramMap.keys的常量paramMapKey){ data.set(paramMapKey,routerChild.paramMap.get(paramMapKey)!); } 返回routerChild.children.reduce((previousValue,currentValue)=>{ 返回ReduceRouteChildrenParams(currentValue,previousValue); },数据); }
您需要递归地遍历路由器树以收集所有参数。 此代码段仅适用于参数键唯一的情况,因此

/home/users/:id/posts/:id/comments/:id
必须是
/home/users/:userId/posts/:postd/comments/:commentId
。如果希望保留旧的paramkey名称,则需要相应地修改代码段

它可能是这样的:

export parseUrl(route: ActivatedRouteSnapshot): Map<string,string> {
  const result = reduceRouterChildrenParams(route.root.firstChild, new Map<string, string>());
  return result;
}

reduceRouterChildrenParams(routerChild: ActivatedRouteSnapshot | null, data: Map<string, string>): RouteWalkerResult {
  if (!routerChild) {
      return data;
  }
  for (const paramMapKey of routerChild.paramMap.keys) {
    data.set(paramMapKey, routerChild.paramMap.get(paramMapKey)!);
  }
  return routerChild.children.reduce((previousValue, currentValue) => {
    return reduceRouterChildrenParams(currentValue, previousValue);
  }, data);
}
导出解析URL(路由:ActivatedRouteSnapshot):映射{ const result=reduceRouterChildrenParams(route.root.firstChild,new Map()); 返回结果; } reduceRouterChildrenParams(routerChild:ActivatedRouteSnapshot | null,数据:Map):RouteWalkerResult{ 如果(!routerChild){ 返回数据; } for(routerChild.paramMap.keys的常量paramMapKey){ data.set(paramMapKey,routerChild.paramMap.get(paramMapKey)!); } 返回routerChild.children.reduce((previousValue,currentValue)=>{ 返回ReduceRouteChildrenParams(currentValue,previousValue); },数据); }
首先,谢谢,它工作得很好。即使不更改具有唯一名称的参数,因为我可以从
router.event
订阅跟踪url更改,然后每次调用您的函数。其次,让我再问你一件事:ActivatedRouteSnapshot的
root
属性相对于当前url段(我的意思是,它代表当前url段的父级)还是始终存储路由器匹配的第一个url段的值(因此,在这种情况下,它将始终等于
/home
,无论我在
/home/users
/home/users/:id/posts/
)中访问它,它始终是最顶级的路由器,与延迟加载的模块或您可以对路由执行的其他操作无关,因此从哪个路由开始并不重要(在您的问题中,例如
/home/users
/home/users/:id/posts/
,但它也适用于任何完全不同的路线)您可以访问该方法。它不适用于名为
id
的每个参数的原因是
Map
数据类型覆盖了同名的条目,不是吗?完全正确,因此您需要:1.调整您