【问题标题】:How to get :id param of child route from parent component in Angular2如何从Angular2中的父组件获取子路由的:id参数
【发布时间】:2017-05-24 00:35:41
【问题描述】:

我正在尝试获取在

中定义的 :id 参数
RouterModule.forRoot([
  {
    path: 'orders',
    component: ListComponent,
    children: [
      {
        path: 'view/:id',
        component: ViewComponent
      },
    ]
  }
])

来自ListComponent

我已经试过了:

route: ActivatedRoute

route.params.subscribe(params => {
  let id = +params['id'];
})

来自ListComponent,但是params数组是空的,我想这是因为:id参数属于ViewComponent而不是ListComponent

如何在ListComponent 中获取id 参数?

【问题讨论】:

    标签: angular routes route-parameters


    【解决方案1】:

    另一种方法是在父组件中添加以下内容:

    <ng-container *ngIf="routerOutlet.isActivated && routerOutlet.activatedRoute?.paramMap | async as paramMap">
    child id is: {{paramMap.get('id')}}!
    </ng-container>
    
    <router-outlet #routerOutlet="outlet"></router-outlet>
    

    当然,在子节点上使用解析器而不是参数会更好

    <ng-container *ngIf="routerOutlet.activatedRouteData['child'] as child">
    child id is : {{child.id}}
    </ng-container>
    
    <router-outlet #routerOutlet="outlet"></router-outlet>
    

    假设子路由有类似的东西:

    // ...
    resolve: {
     child: 'childResolver',
    },
    

    子解析器可以在某个模块中:

    // ...
    providers: [{
        provide: 'childResolver',
        useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => ({
          id: route.paramMap.get('id')
        })
      }],
    

    【讨论】:

      【解决方案2】:

      递归查找子参数不会总能得到您正在寻找的参数。特别是在移动路线时。

      相反,可以使用 RxJS ReplaySubject 发布当前子 ID。

      创建一个新服务:

      @Injectable()
      export class ChildIdService  {
        current$ = new ReplaySubject<number>();
      }
      

      在子组件上导入并订阅重播主题:

      export class ChildComponent implements OnInit {
        constructor(private ar: ActivatedRoute, public ci: ChildIdService){}
      
        ngOnInit(){
          this.ar.params.map(params => +params.id).subscribe(this.ci.current$);
        }
      }
      

      在父组件上导入服务,使用异步管道订阅子值:

      <span>Mother component child ID: {{ci.current$ | async}}</span>
      

      这是一个有效的 sn-p:https://stackblitz.com/edit/angular-b8xome(将 /child/42 添加到浏览器应用预览以查看它是否有效)


      或者将组件定义为同级并将父级添加为无组件路由,例如:https://vsavkin.com/the-powerful-url-matching-engine-of-angular-router-775dad593b03 在“使用相同数据的同级组件”下

      【讨论】:

      • 使用 ReplaySubject 而不是其他类型的主题有什么特别的原因吗?我仍在尝试掌握它们的用例,因此在这个示例中理解它会有所帮助。
      • ReplaySubject 将记住之前的结果,使 observable 对任何未来的订阅都是热的。如果您在多个地方订阅了这个 observable,并且想要访问之前推送的结果,这将很有帮助。
      【解决方案3】:

      为了在父组件中获取子组件的参数,我使用了 ActivatedRoute 的 firstChild 属性,因为我只有子路由

      route: ActivatedRoute
      
      route.firstChild.params.subscribe(params => {
        let id = +params['id'];
      });
      

      【讨论】:

      • 唯一正确的答案,因为在 Angular 中事情永远不会同步发生,而且这个答案也涵盖了订阅(异步)部分。
      【解决方案4】:

      您可以使用firstChild 属性或ActivatedRoute 来获取子路由:

      route.firstChild.snapshot.params['id']
      

      【讨论】:

      • 看起来属性 routerState 在 ActivatedRoute 上不存在,我也想在父组件而不是子组件中获取 id,所以我使用了 route.firstChild.params
      • 我有点误读了这个问题,并假设@runyard 回答了你真正想要的。我更新了我的答案。
      • 我使用了 route.snapshot.firstChild,而不是 route.firstChild.snapshot 还要检查 firstChild 是先定义的
      • 在子加载之前不会有子参数。例如,您可以将 ActivatedRoute 注入子组件,并使子组件将参数传递给共享服务。
      • 它正在工作,但我在控制台中遇到错误,类似“错误错误:ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:'true'。当前值:'false'”
      【解决方案5】:

      如果只有一个子路由,您可以继续挖掘route.firstChild.params['id'],或者使用route.children[0].children[1].params['id'] 之类的东西使用括号表示法来挖掘多个级别以访问同级路由。在找到正确的水平时,它有点反复试验。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-11
        • 2018-02-04
        • 2018-11-14
        • 2016-07-24
        • 2016-09-04
        • 2016-08-28
        • 1970-01-01
        • 2016-11-25
        相关资源
        最近更新 更多