在Angular2中订阅router.events.subscribe时,如何从Route或ActivatedRoute获取数据?

在Angular2中订阅router.events.subscribe时,如何从Route或ActivatedRoute获取数据?,angular,angular-ui-router,Angular,Angular Ui Router,我试图在路由改变时从路由器获取数据,但没有成功。这里我设置了asdf属性 @NgModule({ bootstrap: [AppComponent], declarations: [ AppComponent, LoginComponent, DashboardComponent, OverviewComponent, ], imports: [ BrowserModule, FormsModule, RouterModul

我试图在路由改变时从路由器获取数据,但没有成功。这里我设置了
asdf
属性

@NgModule({
  bootstrap: [AppComponent],
  declarations: [
    AppComponent,
    LoginComponent,
    DashboardComponent,
    OverviewComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot([
      { path: '', pathMatch: 'full', redirectTo: '' },
      { component: LoginComponent, path: 'login' },
      {
        children: [
          { path: '', pathMatch: 'full', redirectTo: 'overview', data: { asdf: 'hello' } },
          { component: OverviewComponent, path: 'overview', data: { asdf: 'hello' } },
        ], component: DashboardComponent,
        path: '',
      },
    ]),
  ],
})
export class AppModule { }
在这里,当路由发生变化,但
asdf
未定义时,我可以从路由器获取URL:(

如何获取asdf的值


编辑:我正在导航到
/overview

路由中的数据必须是一个对象数组,而不仅仅是一个对象,所以像这样定义它们

{ component: LoginComponent, path: 'login', data:[{myKey1: myValue1}] },
现在要检索它,请在组件构造函数中使用此代码

constructor(private router:Router, private activeRoute:ActivatedRoute) {

  router.events
    .filter(event => event instanceof NavigationEnd)
    .map(_ => this.router.routerState.root)
    .map(route => {
      while (route.firstChild) route = route.firstChild;
      return route;
    })
  .flatMap(route => route.data)
  .subscribe(data => {
    console.log(data[0].myKey1);

    });

}
大概是这样的:

constructor(private router: Router, 
        private activatedRoute: ActivatedRoute)
{

 this.router.events
        .filter(event => event instanceof NavigationEnd)
        .map(() => this.activatedRoute)
        .map(route => route.firstChild)
        .switchMap(route => route.data)
        .map(data => data['asdf'])
}
this.router.events.pipe(
    filter(event => event instanceof ActivationEnd),
    map(event => (<ActivationEnd>event).snapshot),
    map(snapshot => (<ActivatedRouteSnapshot>snapshot).data)).subscribe(data => {
        console.log('data from the NEW route: ' + data);
    });
  • 对于来自路由器的每个事件,我只过滤NavigationEnd事件
  • 然后将此事件映射到activatedRoute(因为我想在NavigationEnd上读取activatedRoute的值)
  • 我将activatedRoute映射到firstChild(使用RouterModule.forRoot()声明的第一个子项)
  • 然后制作一个开关图来获取该路线的数据,一个开关图,因为数据是可观察的
  • 最后,我将数据对象映射到我想要的键,在本例中为asdf

  • 以下内容已更新,可用于rxjs v6

    constructor(private router: Router, 
            private activatedRoute: ActivatedRoute)
    {
    
       this.router.events
            .pipe(
             filter(event => event instanceof NavigationEnd),
             map(() => this.activatedRoute),
             map(route => route.firstChild),
             switchMap(route => route.data),
             map(data => data['asdf']))
    }
    

    下面是一个使用@Neelavar-example的修改示例

    它可能看起来很长,但很简单,要有耐心,如果你坚持到底,它应该会起作用。只需按照概述的步骤进行操作就需要几分钟

    我的设置的完整解释,为初学者 您应该已经知道如何创建组件和设置布线,我不会详细解释。 1.在Routes数组中设置数据属性 在您的routes数组中(您可以在app.module.tsapp routes.module.ts或在某些情况下在routes.ts文件中找到)

    如果找不到,请在中检查基本路由设置:

    您只需要一个基本设置!

    像这样添加数据属性(需要生成主组件): 2.创建一个类 RouteData.ts,我把它放在与app.module.ts

    export class RouteData {
      title: string;
    }
    
    这只是为了添加类型以使用typescript中的observable,如果我稍后将其添加到数据类中,IDE可以为我自动完成“title”或“id”或“animation”

    3.将以下内容导入app.component.ts 然后在构造函数的上方声明变量

    routeData$: Observable<RouteData>;
    
    4.然后再次在构造函数内部 根据@Tuizi示例注释改编的代码说明:

    • 对于来自路由器的每个事件,仅过滤NavigationEnd事件(当路由器完成导航时)

    • 然后映射(返回)当前激活的路由

    • 将activatedRoute映射到第一个子级(路由器状态树中此路由的第一个子级)

    • 然后switchMap会发出此路由的数据,使用switchMap因为发出的每个“数据”都是可观察的,所以当发出新的可观察数据时,switchMap会取消旧的可观察数据,从而节省内存

    • 映射(返回)数据对象,为其指定RoutedData类型

    • 最后,您可以在使用异步管道的模板中使用此可观察性

    
    {{routeData.title}titlecase}
    
    *注意:“async as”此时会中断模板中的类型检查:(


    如果您第一次在浏览器中加载路由时点击该路由,则ActivateRoute将具有当前数据。但是,如果您随后单击导致第二个路由器导航的内容,则该第二个路由的ActivateRoute实例将具有原始路由的信息。这可能是因为它不是在将路由注入构造函数时,他激活了路由

    但是,有一个已更新的ActivatedRouteSnapshot实例与ActivationEnd事件关联,因此您可以如下方式访问数据:

    constructor(private router: Router, 
            private activatedRoute: ActivatedRoute)
    {
    
     this.router.events
            .filter(event => event instanceof NavigationEnd)
            .map(() => this.activatedRoute)
            .map(route => route.firstChild)
            .switchMap(route => route.data)
            .map(data => data['asdf'])
    }
    
    this.router.events.pipe(
        filter(event => event instanceof ActivationEnd),
        map(event => (<ActivationEnd>event).snapshot),
        map(snapshot => (<ActivatedRouteSnapshot>snapshot).data)).subscribe(data => {
            console.log('data from the NEW route: ' + data);
        });
    
    this.router.events.pipe(
    过滤器(事件=>ActivationEnd的事件实例),
    映射(事件=>(事件).snapshot),
    映射(快照=>(快照).data)).subscribe(数据=>{
    log('来自新路由的数据:'+数据);
    });
    
    我认为这是一个已知的问题。您可以尝试使用
    setTimeout(()=>console.log(this.activatedRoute.snapshot.data['asdf'))
    ?不幸的是,它不起作用。今天有人建议使用
    Observable.zip()提出了类似的问题
    this.activatedRoute.snapshot.data
    this.router.events
    。你是说这个吗?:正是……。这不是界面建议的:
    导出声明类型数据={[name:string]:any;}
    @MildFuzz it dosent suggest other它的意思是
    Data
    数据的别名,它的类型是
    any
    ,也可以是数组。但是如果订阅router.events并检查类型,您会发现它是数组。如果您在子组件中使用数据,则此处的while循环有助于获取边缘r路由(数据所在的位置)。对于来自
    路由器的每个事件,我只过滤
    导航结束
    事件,然后将此事件映射到
    激活的路由
    (因为我想读取
    导航结束
    上的
    激活的路由
    的值)。我将
    激活的路由
    映射到
    第一个孩子
    (使用
    RouterModule.forRoot()声明的第一个子级然后制作一个
    switchMap
    来获取这条路线的数据,一个switchMap,因为数据是可观察的。最后我将
    data
    对象映射到我想要的键,在这种情况下,
    asdf
    属性“filter”不存在于类型“可观察的”
    可能是因为angular 6和rxjs 6的变化。你能发布upd吗ated代码?似乎不适用于惰性加载模块内的激活路由…第四步应在构造函数中完成,否则有可能
    constructor(
        private router: Router,
        private activatedRoute: ActivatedRoute,
      ) {}
    
      constructor(
        private router: Router,
        private activatedRoute: ActivatedRoute,
      ) {
    
        this.routeData$ = router.events.pipe(
          filter(routeEvent => routeEvent instanceof NavigationEnd),
          map(() => activatedRoute),
          map(activatedRoute => activatedRoute.firstChild),
          switchMap(firstChild => firstChild.data),
          map((data: RouteData) => data)
          );
    
      }
    
        <span *ngIf="routeData$ | async as routeData">
            {{ routeData.title | titlecase }}
          </span>
    
    this.router.events.pipe(
        filter(event => event instanceof ActivationEnd),
        map(event => (<ActivationEnd>event).snapshot),
        map(snapshot => (<ActivatedRouteSnapshot>snapshot).data)).subscribe(data => {
            console.log('data from the NEW route: ' + data);
        });