26

给定路由配置

{
   path: '/root/:rootId',
   children: [{
       path: '/child1/:child1Id',
       children: [{
           path: '/child2/:child2Id
           component: TestComponent
       }]
   }]
}

在 TestComponent 中,如何轻松获取所有路由参数。我想知道是否有比这更简单的方法

let rootId = route.parent.parent.snapshot.params;
let child1Id = route.parent.snapshot.params;
let child2Id = route.snapshot.params;

这似乎过于多余,特别是如果我正在观察可观察的路由参数而不是通过路由快照访问参数。这种方法似乎也很脆弱,因为如果我移动了任何路线/参数,它就会中断。我习惯于有角度的 ui-router,其中为单个对象 $stateParams 提供了所有易于访问的参数数据。我对从路由树中的单个节点访问的路由解析数据也有同样的担忧。任何帮助将非常感激。提前致谢

4

8 回答 8

66

从 Angular 5.2 开始,您可以进行路由器配置以将所有参数继承到子状态。如果对血腥细节感兴趣,请参阅此提交,但这是它对我的工作方式:

无论您在哪里调用RouterModule.forRoot(),都包含一个配置对象,其继承策略设置为always(默认为emptyOnly):

import {RouterModule, ExtraOptions} from "@angular/router";

export const routingConfiguration: ExtraOptions = {
  paramsInheritanceStrategy: 'always'
};

export const Routing = RouterModule.forRoot(routes, routingConfiguration);

现在,当您在子组件中查看 a 时ActivatedRoute,祖先的参数出现在那里(例如activatedRoute.params),而不是像activatedRoute.parent.parent.parent.params. 您可以直接访问该值(例如activatedRoute.params.value.userId)或通过订阅activatedRoute.params.subscribe(...)

于 2018-01-29T23:11:59.680 回答
6

您需要迭代路线段。

就像是

var params = [];
var route = router.routerState.snapshot.root;
do {
 params.push(route.params); 
 route = route.firstChild;
} while(route);

这为您提供params了每个路线段的列表,然后您可以从中读取所需的参数值。

Object.keys(params)可能可以从param实例中获取所有可用的参数名称。

于 2017-02-17T15:32:31.987 回答
2
constructor(private route: ActivatedRoute) {}

data$ = of(this.route).pipe(
    expand(route => of(route['parent'])),
    takeWhile(route => !!route['parent']),
    pluck('snapshot', 'data'),
    reduce(merge));

解释:

在这里调用 expand 会为父链中的每个路由创建一个 observable。使用 Takewhile 以便在 route['parent'] 返回 null 时或在根路由处停止递归。

然后,对于 observable 中的所有这些路由,pluck 会将每个路由映射到它的 'snapshot.data' 属性。

最后,从 lodash 为 reduce 提供了合并功能,以将所有数据对象合并为一个对象。此流通过父路由聚合来自当前路由的所有数据

于 2017-12-06T04:51:20.103 回答
1

从所有活动的 Outlets 路由参数

如果您有一个用例,您需要从primary outleta 中路由的组件中了解参数secondary outlet,则此函数会递归地收集来自所有活动插座的所有参数:

const getParams = (route) => ({
  ...route.params,
  ...route.children.reduce((acc, child) =>
    ({ ...getParams(child), ...acc }), {}) 
});

getParams(router.routerState.snapshot.root);

如果当前 URL 是/path/to/42(outlet:path/to/99),则结果对象可能是:

{ primaryParam: '42', outletParam: '99' }

对象中的键取决于您在 Angular 中的路由配置。

于 2021-04-03T12:50:22.997 回答
1
/**
 * Get all activated route snapshot param under lazy load modules
 * @see RouterModule.forChild(routes)
 */
public static getSnapshotParams(route: ActivatedRoute): { [key: string]: string } {
    const params: { [key: string]: string } = {};
    do {
        const param = route.snapshot.params;
        for (let key in param) {
            params[key] = param[key];
        }
        route = route.parent;
    } while (route);
    return params;
}

/**
 * Get all activated route stream observable param under lazy load modules
 * @see RouterModule.forChild(routes)
 * @see Observable
 * @see Params
 */
public static getRouteParam(route: ActivatedRoute, routeKey: string): Observable<number> {
    const obs: Observable<Params>[] = [];
    do {
        obs.push(route.params);
        route = route.parent;
    } while (route);
    return merge(...obs).pipe(
        filter(param => !!param[routeKey]),
        map(param => param[routeKey])
    );
}

}

于 2021-01-28T19:34:10.347 回答
0

我创建了以下服务,以便能够将所有路由参数作为ParamMap 获取。它背后的主要思想是递归地解析子路由中的所有参数。

Github 要点

import {Injectable} from '@angular/core';
import {
  ActivatedRoute,
  Router,
  NavigationEnd,
  ParamMap,
  PRIMARY_OUTLET,
  RouterEvent
} from '@angular/router';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';

@Injectable()
export class ParamMapService {

  paramMap: Observable<ParamMap>;

  constructor(private router: Router,
              private route: ActivatedRoute) {
    this.paramMap = this.getParamMapObservable();
  }

  private getParamMap(route: ActivatedRoute): ParamMap {
    const map: Map<string, string | string[]> = new Map();

    while (route) {
      route.snapshot.paramMap.keys.forEach((key) => {
        map.set(key, this.getParamMapValue(route.snapshot.paramMap, key));
      });
      route = route.firstChild;
    }

    return <ParamMap>{
      keys: this.getParamMapKeys(map),
      has: this.getParamMapMethodHas(map),
      get: this.getParamMapMethodGet(map),
      getAll: this.getParamMapMethodGetAll(map)
    };
  }

  private getParamMapMethodGet(map: Map<string, string | string[]>): (name: string) => string | null {
    return (name: string): string | null => {
      const value = map.get(name);
      if (typeof value === 'string') {
        return value;
      }
      if (Array.isArray(value) && value.length) {
        return value[0];
      }
      return null;
    };
  }

  private getParamMapMethodGetAll(map: Map<string, string | string[]>): (name: string) => string[] {
    return (name: string): string[] => {
      const value = map.get(name);
      if (typeof value === 'string') {
        return [value];
      }
      if (Array.isArray(value)) {
        return value;
      }
      return [];
    };
  }

  private getParamMapMethodHas(map: Map<string, string | string[]>): (name: string) => boolean {
    return (name: string): boolean => map.has(name);
  }

  private getParamMapKeys(map: Map<string, string | string[]>): string[] {
    return Array.from(map.keys());
  }

  private getParamMapObservable(): Observable<ParamMap> {
    return this.router.events
      .filter((event: RouterEvent) => event instanceof NavigationEnd)
      .map(() => this.route)
      .filter((route: ActivatedRoute) => route.outlet === PRIMARY_OUTLET)
      .map((route: ActivatedRoute) => this.getParamMap(route));
  }

  private getParamMapValue(paramMap: ParamMap, key: string): string | string[] {
    return (paramMap.getAll(key).length > 1 ? paramMap.getAll(key) : paramMap.get(key));
  }
}

示例用法

id;

constructor(private paramMapService: ParamMapService) {
  this.paramMapService.paramMap.subscribe(paramMap => {
    this.id = paramMap.get('id');
  });
}

笔记

ES6 Map正在服务中使用。要支持旧版浏览器,请执行以下操作之一:

  • 取消注释import 'core-js/es6/map';,polyfills.ts
  • 将所有 Map 实例转换为一个简单对象。
于 2018-05-09T23:14:54.043 回答
0

角度 5:

import { combineLatest } from 'rxjs/observable/combineLatest';



 constructor(
    private activatedRoute: ActivatedRoute
  ) {
    combineLatest(
      this.activatedRoute.data,
      this.activatedRoute.params
    ).subscribe(([{from}, params]) => {
      this.params.from = from;
      this.params.id = params['id'];
      this.loadData();
    });
  }
于 2018-12-26T14:40:16.403 回答
-1

我以这种方式获得了第一个路由参数:

console.log(this.route.snapshot.firstChild.params)

于 2017-08-14T23:36:28.923 回答