Angular 角度2:从父组件获取RouteParams

Angular 角度2:从父组件获取RouteParams,angular,angular2-routing,Angular,Angular2 Routing,如何从父组件获取路由图 App.ts: @Component({ ... }) @RouteConfig([ {path: '/', component: HomeComponent, as: 'Home'}, {path: '/:username/...', component: ParentComponent, as: 'Parent'} ]) export class HomeComponent { ... } @Component({ ... }) @Rout

如何从父组件获取路由图

App.ts

@Component({
  ...
})

@RouteConfig([
  {path: '/', component: HomeComponent, as: 'Home'},
  {path: '/:username/...', component: ParentComponent, as: 'Parent'}
])

export class HomeComponent {
  ...
}
@Component({
  ...
})

@RouteConfig([
  { path: '/child-1', component: ChildOneComponent, as: 'ChildOne' },
  { path: '/child-2', component: ChildTwoComponent, as: 'ChildTwo' }
])

export class ParentComponent {

  public username: string;

  constructor(
    public params: RouteParams
  ) {
    this.username = params.get('username');
  }

  ...
}
然后,在
ParentComponent
中,我可以轻松获取用户名参数并设置子路由

Parent.ts

@Component({
  ...
})

@RouteConfig([
  {path: '/', component: HomeComponent, as: 'Home'},
  {path: '/:username/...', component: ParentComponent, as: 'Parent'}
])

export class HomeComponent {
  ...
}
@Component({
  ...
})

@RouteConfig([
  { path: '/child-1', component: ChildOneComponent, as: 'ChildOne' },
  { path: '/child-2', component: ChildTwoComponent, as: 'ChildTwo' }
])

export class ParentComponent {

  public username: string;

  constructor(
    public params: RouteParams
  ) {
    this.username = params.get('username');
  }

  ...
}
但是,如何在这些子组件中获得相同的“username”参数?做同样的把戏,如上所述,没有做到这一点。因为这些参数是在ProfileComponent或其他地方定义的

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

  constructor(
    public params: RouteParams
  ) {
    this.username = params.get('username');
    // returns null
  }

  ...
}

我找到了一个丑陋但有效的解决方案,通过请求父(确切地说是第二个祖先)注入器,并从这里获取
RouteParams

差不多

@Component({
  ...
})
export class ChildOneComponent {
  public username: string;

  constructor(injector: Injector) {
    let params = injector.parent.parent.get(RouteParams);

    this.username = params.get('username');
  }
}

正如Günter Zöchbauer所提到的,我使用了在上的评论来解决我的问题。我使用
angular2/core
中的
Injector
类获取父级的路由图。结果表明,angular 2不处理深度嵌套的管线。也许他们将来会加上这个

constructor(private _issueService: IssueService,
            private _injector: Injector) {}

getIssues() {
    let id = this._injector.parent.parent.get(RouteParams).get('id');
    this._issueService.getIssues(id).then(issues => this.issues = issues);
}

您可以从注入器获取子组件内部的父路由组件,然后从子组件获取任何组件。在你这样的情况下

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

  constructor(
    public params: RouteParams
    private _injector: Injector

  ) {
    var parentComponent = this._injector.get(ParentComponent)

    this.username = parentComponent.username;
    //or
    this.username = parentComponent.params.get('username');
  }

  ...
}

若要为代码编写单元测试,将注入器实例传递给子组件中的构造函数可能不太好

解决这个问题的最简单方法是在父组件中有一个服务类,您可以在其中保存所需的参数

@Component({
    template: `<div><router-outlet></router-outlet></div>`,
    directives: [RouterOutlet],
    providers: [SomeServiceClass]
})
@RouteConfig([
    {path: "/", name: "IssueList", component: IssueListComponent, useAsDefault: true}
])
class IssueMountComponent {
    constructor(routeParams: RouteParams, someService: SomeServiceClass) {
        someService.id = routeParams.get('id');
    }
}
请注意,您应该使用父组件装饰器中的“提供者”将此类服务的范围限定到父组件及其子组件


我推荐这篇关于Angular 2中DI和作用域的文章:

您不应该尝试在
ChildOneComponent
中使用
RouteParams

使用,而不是

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

  constructor(registry: RouteRegistry, location: Location) {
    route_registry.recognize(location.path(), []).then((instruction) => {
      console.log(instruction.component.params['username']);
    })
  }


  ...
}
更新:从本次拉动请求(angular beta.9)开始:

您现在可以访问当前指令,而无需识别(location.path(),[])

例如:

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

  constructor(_router: Router) {
    let instruction = _router.currentInstruction();
    this.username = instruction.component.params['username'];
  }

  ...
}
我还没有试过,但是

import { ActivatedRoute, Router, ParamMap } from '@angular/router';
详情如下:

更新2: 角度2.0.0.beta15的微小变化:

现在
currentInstruction
不再是一个函数。此外,您必须加载
路由器。(感谢@Lxrd AJ的报道)


最后我为Angular 2 rc.1写了这样一篇文章

从'@angular/Router deprecated'导入{Router};
从“lodash”导入*as uuu;
接口参数对象{
[键:字符串]:任意[];
};
/**
*遍历route.parent链接直到根路由器并检查每个级别
*将当前指令和组参数设置为单个对象。
*
*例如。
* {
*身份证号码:[314593],
*其他参数:[9]
* }
*/
导出默认函数mergeRouteParams(路由器:路由器):ParameterObject{
让mergedParameters:ParameterObject={};
while(路由器){
让currentInstruction=router.currentInstruction;
如果(当前指令){
设currentParams=currentInstruction.component.params;
_.每个(当前参数,(值,键)=>{
设valuesForKey=mergedParameters[key]| |[];
值关闭。取消移位(值);
mergedParameters[键]=值键;
});
}
路由器=router.parent;
}
返回合并参数;
}
现在在视图中,我收集视图中的参数,而不是读取
RouteParams
,我只是通过路由器获取它们:

@组件({
...
})
导出类ChildishComponent{
构造器(路由器:路由器){
设allParams=mergeRouteParams(路由器);
让parentRouteId=allParams['id'][0];
让childRouteId=allParams['id'][1];
设otherRandomParam=allParams.otherRandomParam[0];
}
...
}  

更新:

现在Angular2决赛正式发布,正确的方法如下:

export class ChildComponent {

    private sub: any;

    private parentRouteId: number;

    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        this.sub = this.route.parent.params.subscribe(params => {
            this.parentRouteId = +params["id"];
        });
    }

    ngOnDestroy() {
        this.sub.unsubscribe();
    }
}

原件:

下面是我如何使用“@angular/router”:“3.0.0-alpha.6”包实现的:

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

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

RC5+@angular/router:“3.0.0-rc.1解决方案:似乎
此.router.routerState.queryParams
已被弃用。可以通过以下方式获取父路由参数:

constructor(private activatedRoute: ActivatedRoute) {
}    

this.activatedRoute.parent.params.subscribe(
  (param: any) => {
    let userId = param['userId'];
    console.log(userId);
  });

在RC6路由器3.0.0-rc.2中(可能也适用于RC5),您可以将URL中的路由参数作为快照,以防参数不会改变,而不使用以下一行代码进行观察:

this.route.snapshot.parent.params['username']

不要忘记按如下方式注入ActivatedRoute:


构造函数(私有路由:ActivatedRoute){}

最终版中RXJS的帮助下您可以组合两个贴图(从子贴图和父贴图):

人们可能会有其他问题:

  • 使用上面的方法真的是一个好主意吗?因为耦合(将子组件与父组件的参数耦合-不在api级别-隐藏耦合)
  • 就RXJS而言,这是正确的方法吗(需要铁杆RXJS用户反馈;)

通过RxJS的
可观察。CombineTest
,我们可以得到一些接近惯用参数处理的东西:

导入'rxjs/add/operator/combinelateest';
从'@angular/core'导入{Component};
从“@angular/router”导入{ActivatedRoute,Params};
从“rxjs/Observable”导入{Observable};
@组件({/*…*/})
导出类组件{
电子邮件:字符串;
id:字符串;
构造函数(专用路由:ActivatedRoute){}
恩戈尼尼特(){
Observable.CombineTest(this.route.params,this.route.parent.params)
.forEach((params:params[])=>{
this.id=params[0]['id'];
this.email=params[1]['email'];
});
}
}

您可以在快照上执行以下操作,但如果更改,您的
id
属性将不会更新

该示例还显示了如何订阅所有祖先参数更改,并通过合并所有参数可观测值来查找您感兴趣的更改。然而
(route) => Observable
    .zip(route.params, route.parent.params)
    .map(data => Object.assign({}, data[0], data[1]))
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
constructor(private activatedRoute: ActivatedRoute, private router: Router) { }
this.activatedRoute.parent.paramMap.subscribe((params: ParamMap) => this.studentId = (params.get('student_id')));