Angular 2新路由器:如何获取子组件的路由器参数?

Angular 2新路由器:如何获取子组件的路由器参数?,angular,typescript,rxjs,angular2-routing,Angular,Typescript,Rxjs,Angular2 Routing,在最新版本的@angular/router3.0.0-rc.1中,从URL/路由获取参数的方式发生了变化 根据文档,您应该能够通过订阅参数来获取参数,但在我的情况下,这似乎不起作用 我想要实现的是将参数从子路由获取到父组件中 例如,假设这是我的路线: const routes: Routes = [ { path: 'parent', component: ParentComponent, pathMatch: 'prefix', children: [

在最新版本的
@angular/router
3.0.0-rc.1
中,从URL/路由获取参数的方式发生了变化

根据文档,您应该能够通过订阅参数来获取参数,但在我的情况下,这似乎不起作用

我想要实现的是将参数从子路由获取到父组件中

例如,假设这是我的路线:

const routes: Routes = [
  {
    path: 'parent',
    component: ParentComponent,
    pathMatch: 'prefix',
    children: [
      {
        path: ':id',
        component: ChildComponent
      }
    ]
  }
];
我想获取
id
参数并在我的ParentComponent中使用它。 所以我试着这样做:

export class ParentComponent implements OnInit {

  sub: any;
  constructor(
    private route: ActivatedRoute) {
    this.route = route;
   }

  ngOnInit() {

    this.sub = this.route.params.subscribe(params => {
     let id = params['id'];
     console.log(id);
   });

  }

}
就像这样,我得到:

未定义


我在这里遗漏了什么?

ActivatedRoute具有访问其父/子路由信息的getter

为了从父级访问第一个子路由,您将使用:

this.route.firstChild.params

  this.router.events.subscribe(event => {
            if (event instanceof RoutesRecognized) {
                // let strId = event.state.root.firstChild.children[0].data;
                let a = event.state.root.firstChild.children.map((route) => {
                    while (route.firstChild) {
                        route = route.firstChild;
                    }

                    return route;
                });
                console.log('Title', a[0].data.title);
                this.meta.updateTitle(a[0].data.title);
            }
            if (event instanceof NavigationEnd) {
                (<any>window).gtag('config', this.googleAnalyticsCode, {
                    'page_title' : this.titleService.getTitle(),
                    'page_path': event.urlAfterRedirects
                });
            }
        });
如果需要所有子路由,可以使用
children
属性。这将返回一个
ActivatedRoute

this.route.children

如果您在子管线中,并且需要来自父管线的参数:


this.route.parent.params

子参数与子参数关联/存储。它们在父级的ActivatedRoute上不可用。因此,首先需要使用getter
firstChild
children
获取孩子的ActivatedRoute

  this.router.events.subscribe(event => {
            if (event instanceof RoutesRecognized) {
                // let strId = event.state.root.firstChild.children[0].data;
                let a = event.state.root.firstChild.children.map((route) => {
                    while (route.firstChild) {
                        route = route.firstChild;
                    }

                    return route;
                });
                console.log('Title', a[0].data.title);
                this.meta.updateTitle(a[0].data.title);
            }
            if (event instanceof NavigationEnd) {
                (<any>window).gtag('config', this.googleAnalyticsCode, {
                    'page_title' : this.titleService.getTitle(),
                    'page_path': event.urlAfterRedirects
                });
            }
        });
然后,父级可以订阅子级参数更改:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute }               from '@angular/router';
import { Subscription }                 from 'rxjs/Subscription';

export class ParentComponent implements OnInit, OnDestroy {
   private sub: Subscription;
   constructor(private route: ActivatedRoute) {}
   ngOnInit() {
      this.sub = this.route.firstChild.params.subscribe(
        params => console.log(params.id));
   }
   ngOnDestroy() {
      this.sub.unsubscribe();
   }
}
也可以获取子参数的快照:

import { Component }      from '@angular/core';
import { ActivatedRoute } from '@angular/router';

export class ParentComponent {
   constructor(private route: ActivatedRoute) {}
   someMethod() {
      console.log(this.route.firstChild.snapshot.params.id);
   }
}

如果你想得到所有的孩子(例如,如果你有多个出口),使用
ActivatedRoute.children
ActivatedRouteSnapshot.children
获取子ActivatedRoute或子ActivatedRouteShapshots的数组。

通过使用
this.ActivatedRoute.snapshot.firstChild.params
this.router.events.subscribe(event=>{
  this.router.events.subscribe(event => {
            if (event instanceof RoutesRecognized) {
                // let strId = event.state.root.firstChild.children[0].data;
                let a = event.state.root.firstChild.children.map((route) => {
                    while (route.firstChild) {
                        route = route.firstChild;
                    }

                    return route;
                });
                console.log('Title', a[0].data.title);
                this.meta.updateTitle(a[0].data.title);
            }
            if (event instanceof NavigationEnd) {
                (<any>window).gtag('config', this.googleAnalyticsCode, {
                    'page_title' : this.titleService.getTitle(),
                    'page_path': event.urlAfterRedirects
                });
            }
        });
if(路由的事件实例已识别){ //设strId=event.state.root.firstChild.children[0].data; 设a=event.state.root.firstChild.children.map((路由)=>{ while(route.firstChild){ route=route.firstChild; } 返回路线; }); console.log('Title',a[0].data.Title); this.meta.updateTitle(a[0].data.title); } if(NavigationEnd的事件实例){ gtag('config',this.googleAnalyticsCode{ “页面标题”:this.titleService.getTitle(), “页面路径”:event.urlAfterRedirects }); } });
通过ActivatedRoute获取子参数非常容易,但是如果更改当前子参数,您可能会很快遇到问题

首先,请注意:

  • activatedRoute.firstChild
    属性是一个
    activatedRoute
    实例,不可观察
  • 还要注意,
    activatedRoute.paramMap
    是可观察的
以下是您遇到问题的方式:

  • 考虑一个具有两个子路由的组件(以及相应的组件),其中一次只显示一个子路由(例如选项卡式接口)
  • 如果您在
    ngOnInit
    处理程序中访问
    firstChild.paramMap
    ,您将能够订阅它并在参数更改时监视它们。这看起来和工作都很好
  • 如果切换到第二个选项卡,然后返回到第一个选项卡,则所有内容都将中断。这是因为您最初在一个已不存在的ActivateRoute实例上订阅了
    paramMap
  • 重要提示:只有当您试图访问孩子的
    paramMap
    时,这才是一个问题。如果您试图访问“自己的”paramMap,或者子组件也注入了
    paramMap
    ,那么一切都会很好
我找到的最干净的解决方案如下:

注意:除了
路由:ActivatedRoute
之外,首先注入
路由器:路由器

const firstChildParams$ = this.router.events.pipe(filter(e => e instanceof NavigationEnd),
                                                  startWith(undefined),
                                                  switchMap(e => this.route.firstChild!.paramMap));
它只侦听NavigationEnd事件,之后将有一个新的
firstChild
。通过使用
switchMap
,您无需担心取消订阅旧的冗余映射。也不是说从未使用过导航事件的实际值,而且需要
startWith
第一次能够立即处理参数

我一直在收集像这样有用的东西到一个RouterHelper服务中,我可以在任何地方注入,而不必记住所有这些疯狂



有朝一日,我可能会建议,应该有一个可观察的等价物,相当于第一个孩子,那么这就不会是一个问题。然而,它可能会在其他场景中引入更多的混乱

谢谢你@Brandon!嘿@Mark,谢谢你提供的信息性答案,但我们是否总是需要取消订阅?谢谢你的回答!这正是我要找的!太好了:)希望我把所有的细节都弄对了。这些事情变得棘手!我当然也建议创建一个将ActivatedRoute作为依赖项并公开类似内容的服务。然后你可以在任何地方使用它,如果你发现你做错了什么,你只需要在一个地方修复它。