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

ilo*_*amp 10 angular-ui-router angular

我试图在路由改变时从路由器获取数据,但我没有成功.我在这里设置了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 { }
Run Code Online (Sandbox Code Playgroud)

在这里,我可以在路由更改时从路由器获取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 :(
      }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能获得asdf价值?

编辑:我正在导航 /overview

Tui*_*izi 13

没有while循环

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'])
}
Run Code Online (Sandbox Code Playgroud)

  • 似乎不适用于延迟加载的模块内部的激活路由... (2认同)

Tay*_*nza 9

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

它可能看起来很长,但很简单,要有耐心,如果你坚持下去,它应该会奏效。只需按照概述的步骤操作即可花费几分钟时间。

我的设置的完整说明,适合初学者

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

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

在你的路由数组中(你会在app.module.tsapp-routes.module.ts或在某些情况下在routes.ts文件中找到它)。

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

一个基本的设置就是你所需要的!

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

export const routes: Routes = [
  { path: 'home', component: HomeComponent, data: {title: 'home'} },
  { path: '', pathMatch: 'full', redirectTo: '/home' },
];
Run Code Online (Sandbox Code Playgroud)

2.创建一个类

RouteData.ts,我将它放在与app.module.ts相同的文件夹空间中

export class RouteData {
  title: string;
}
Run Code Online (Sandbox Code Playgroud)

这只是为了在打字稿中添加使用 observable 的类型,然后 IDE 可以自动完成“标题”“id”“动画”如果我稍后将其添加到数据类中为我。

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';
Run Code Online (Sandbox Code Playgroud)

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

routeData$: Observable<RouteData>;
Run Code Online (Sandbox Code Playgroud)

然后在构造函数里面

constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute,
  ) {}
Run Code Online (Sandbox Code Playgroud)

4.然后再次构造函数中

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

  }
Run Code Online (Sandbox Code Playgroud)

改编自@Tuizi链接的代码说明示例评论:

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

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

  • 将activatedRoute 映射到firstChild(路由器状态树中该路由的第一个子节点)。

  • 然后一个 switchMap 发出这条路由的数据,使用 switchMap 因为发出的每个“数据”都是一个 observable,当一个新的 observable 发出时,switch map 会取消旧的 observable,节省内存。

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

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

    <span *ngIf="routeData$ | async as routeData">
        {{ routeData.title | titlecase }}
      </span>
Run Code Online (Sandbox Code Playgroud)

*注意:“async as”目前会破坏模板中的类型检查:(

github问题


小智 7

以下内容已更新为可与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']))
}
Run Code Online (Sandbox Code Playgroud)


小智 6

如果您是第一次在浏览器中加载路线时点击路线,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);
    });
Run Code Online (Sandbox Code Playgroud)