【问题标题】:Angular 2: How to pass route parameters to subroute?Angular 2:如何将路由参数传递给子路由?
【发布时间】:2016-09-21 01:48:07
【问题描述】:

使用 Angular 2 rc.1 和 TypeScript。当组件加载到子路由中时,我在将路由参数传递给我的组件时遇到了很多麻烦。我使用@angular/router-deprecated 包。

在我的根组件中,我这样配置路由:

@RouteConfig([
  {path:'/top', name:'Top', component: EndPointComponent},
  {path:'/sub/...', name:'Sub', component: MiddleManComponent}
])

这是我尝试读取参数的端点组件

import {Component} from '@angular/core';
import {RouteParams} from '@angular/router-deprecated';
@Component({
    template: 'Route Params: {{routeParams.params | json}}'
})
export class EndPointComponent{
    constructor(private routeParams:RouteParams){}
}

这是 中间人组件,其中包含到 EndPointComponent 的子路由

import {Component} from '@angular/core';
import {RouteConfig, ROUTER_DIRECTIVES} from '@angular/router-deprecated';
import {EndPointComponent} from "./endpoint.component";

@Component({
    directives: [ROUTER_DIRECTIVES]
    template: `<router-outlet></router-outlet>`
})
@RouteConfig([
    {path: '/end', name: 'End', component: EndPointComponent, useAsDefault: true}
])
export class MiddleManComponent {}

从顶级路由加载组件时,可以从EndPointComponentrouteParams对象成功读取参数(例如:根组件中名为'Top'的路由)。但是,当我通过MiddleManComponent 导航到EndPointComponent 时,参数始终为空(例如:通过根组件中名为“Sub”的路由)。

子路由器在解析路由之前是否会从父路由器中清除参数?这没有多大意义,所以我打赌我错过了一些东西。我的问题很简单:如何将路由参数传递给子路由?

PS:我尝试为demo this setup 构建一个 plunker,但当我无法弄清楚为什么应用程序无法加载时我放弃了。

【问题讨论】:

    标签: typescript routing angular


    【解决方案1】:

    子路由实际上有自己的 RouteParams 实例,与父路由不同。这样做是为了避免命名冲突并促进路由组件的封装。

    您可以通过服务与子路由加载的组件共享父路由的参数。

    @Injectable()
    export class RouteParamService {
      constructor(private routeParams: RouteParams) {}
    
      get params() {
        return this.routeParams.params;
      }
    }
    
    @Component({
        template: 'Route Params: {{routeParams.params | json}}'
    })
    export class EndPointComponent{
        constructor(private routeParams:RouteParamService){}
    }
    
    @Component({
      directives: [ROUTER_DIRECTIVES]
      template: `<router-outlet></router-outlet>`,
      providers: [RouteParamService]
    })
    @RouteConfig([
      {path: '/end', name: 'End', component: EndPointComponent, useAsDefault: true}
    ])
    class MiddleManComponent() { }
    

    RouteParamService 将在与 MiddleManComponent 相同的路由级别实例化,因此将获得相同的 RouteParams 实例。当您的服务被注入您的子路由组件时,您将能够访问父路由参数。

    如果您需要 2 个 EndPointComponent 实例在不同的路由树级别加载,我认为您将需要另一层父路由;即在 RootComponent 之间封装 MiddleManComponent 和 EndPointComponent 的路由组件。

    RootComponent 没有路由,因此您将无法从中为 RouteParamService 实例化 RouteParams。 RouteParams 由&lt;router-outlet&gt; 组件提供。

    【讨论】:

    • 谢谢。这是一个非常有趣的解决方案。这似乎有点hacky,不是吗?据你所知,Angular 2 没有内置的解决方案?我认为我的用例非常普遍,除非我的组件架构构思不当。 PS:如果存在内置解决方案,则可能在@angular/router,而不是较旧的@angular/router-deprecated
    • 当您尝试在不同的路由级别实例化相同的组件时,它确实开始感觉很糟糕。如果您需要顶级路由的参数,那么您基本上需要一个专门用于实例化您的服务并将其他组件向下推一级的组件。这就是为什么我认为顶级组件无法访问 RouteParams 是一个设计错误的原因之一。尽管如此,使用服务在组件之间共享数据是 Angular 应用程序的常见设计模式。
    【解决方案2】:

    使用@angular/router@3.4.7,您可以访问父ActivatedRoute

    export class ChildComponent implements OnInit {
    
      parentRouteId: string;
    
      constructor(private route: ActivatedRoute) {
      }
    
      ngOnInit() {
        this.route.parent.params
          .subscribe((params: Params) => this.parentRouteId = params['id']);
      }
    }
    

    【讨论】:

      【解决方案3】:

      使用 "@angular/router": "3.0.0-alpha.6" 包,我可以通过执行以下操作来获取父路由参数:

      export class ChildComponent {
      
          private sub: any;
      
          private parentRouteId: number;
      
          constructor(
              private router: Router,
              private route: ActivatedRoute) {
          }
      
          ngOnInit() {
              this.sub = this.router.routerState.parent(this.route).params.subscribe(params => {
                  this.parentRouteId = +params["id"];
              });
          }
      
          ngOnDestroy() {
              this.sub.unsubscribe();
          }
      }
      

      在本例中,路由格式如下:/parent/:id/child/:childid

      export const routes: RouterConfig = [
          {
              path: '/parent/:id',
              component: ParentComponent,
              children: [
                  { path: '/child/:childid', component: ChildComponent }]
          }
      ];
      

      【讨论】:

        【解决方案4】:

        您可以注入ActivatedRote 并拍摄快照,更简单:

        constructor(private route: ActivatedRoute) {}; ngOnInit() { console.log('one of my parents route param:', this.route.snapshot.parent.params['PARAM-NAME']); }

        【讨论】:

        • 谢谢。我选择的答案当时对我有用。从那以后,Angular 发生了很大的变化,自从搬到 rc 4rc 5 后,我实际上已经完全按照你的建议做了
        猜你喜欢
        • 2016-09-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多