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

时间:2016-11-17 18:50:43

标签: angular angular-ui-router

我正试图在路由改变时从路由器获取数据,但我没有成功。在这里,我设置了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 { }

此处我可以在路由更改时从路由器获取URL但asdf未定义:(

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ActivatedRoute, NavigationEnd } from '@angular/router';
@Component({
  selector: 'cs-map',
  styleUrls: ['map.component.css'],
  templateUrl: 'map.component.html',
})
export class MapComponent implements OnInit {
  private routerSub;

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

  public ngOnInit() {
    this.router.events.subscribe((val) => {
      if (val instanceof NavigationEnd) {
        let url = val.url;
        console.log(this.activatedRoute.snapshot.data['asdf']); // data is defined but asdf is not :(
      }
    });
  }
}

如何获得asdf的价值?

编辑:我正在导航到/overview

5 个答案:

答案 0 :(得分:7)

没有循环

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'])
}

答案 1 :(得分:4)

以下内容已更新,可与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']))
}

答案 2 :(得分:3)

这是使用@Neelavar link示例的修改示例。

它看起来很长,但是很简单,请耐心等待,如果坚持下去,它应该可以工作。只需按照概述的步骤进行,就需要几分钟。

针对我的设置的完整说明,适用于初学者

您应该已经知道如何创建组件和设置路由,我将不做深入解释。

1。在路由数组中设置数据属性

在路线数组中(您可以在 app.module.ts app-routes.module.ts 中找到它,有时在 routes中找到它) .ts 文件)。

如果找不到,请在以下位置检查基本路由设置:  -angular docs  -a video as well

仅需基本设置!

像这样添加data属性(您将需要生成home组件):

export const routes: Routes = [
  { path: 'home', component: HomeComponent, data: {title: 'home'} },
  { path: '', pathMatch: 'full', redirectTo: '/home' },
];

2。创建一个课程

RouteData.ts ,我将其保存在与 app.module.ts

相同的文件夹空间中
export class RouteData {
  title: string;
}

这仅仅是添加用于在typescript中使用可观察的类型,然后IDE可以自动完成“ title” “ id” “ animation” < / em>如果我以后再将其添加到数据类中。

3。将以下内容导入到app.component.ts

import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { filter, map, switchMap } from 'rxjs/operators';
import { RouteData } from './route-data';

然后在构造函数代码上方,声明变量

routeData$: Observable<RouteData>;

然后在构造函数

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

4。然后在 ngOnInit

ngOnInit() {

    this.routeData$ = this.router.events.pipe(
      filter(routeEvent => routeEvent instanceof NavigationEnd),
      map(() => this.activatedRoute),
      map(activatedRoute => activatedRoute.firstChild),
      switchMap(firstChild => firstChild.data),
      map((data: RouteData) => data)
      );

  }

来自@Tuizi link示例注释的代码说明:

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

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

  • 将ActivatedRoute映射到firstChild(路由器状态树中此路由的第一个孩子)。

  • 然后,switchMap会发出此路由的数据,请使用switchMap,因为发出的每个“数据”都是可观察的,当发出新的数据时,switch映射会取消旧的可观察的对象,从而节省了内存。

  • 映射(返回)数据对象,为其分配一种RouteData类型。

  • 最后,您可以使用异步管道在模板中使用此Observable

    <span *ngIf="routeData$ | async as routeData">
        {{ routeData.title | titlecase }}
      </span>

*注意:“异步为”会中断模板中的类型检查:(

github issue

答案 3 :(得分:2)

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

但是,有一个与ActivationEnd事件相关联的ActivatedRouteSnapshot的更新实例,因此您可以像这样访问数据:

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);
    });

答案 4 :(得分:0)

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

{ 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);

    });

}