Angular 2路由器事件第一次没有开火?

问题描述 投票:15回答:5

我正在从一个组件路由到另一个组件。路线完成后,我想使用上一条路线的URL。我已将下面的代码放入要路由到的组件的构造函数中,但它不会在第一个路径上触发。在第一个路径之后,该功能每次都会触发。

this.router.events
      .filter(e => e instanceof NavigationEnd)
      .pairwise().subscribe((e) => {
          console.log(e);
    });

如果我删除成对功能,它似乎在第一条路线上触发,但它只列出当前路线,而不是前一路线。

 router.events
  .filter(e => e instanceof NavigationEnd)
  .subscribe(e => {
    console.log(e);
 });

我的目标是在新组件路由到时检索先前的路由。我在这做错了什么?

angular angular2-routing
5个回答
5
投票

我有完全相同的情况,我发现it's too late在子组件的构造函数中使用pairwise订阅NavigationEnd。

您可以订阅根组件中的路由器,并通过服务共享路由数据,如下例所示:

events.service.ts

import { Injectable } from '@angular/core';
import { RouteChanged } from '../models/route-changed.model';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class EventsService {
  public routeChanged = new BehaviorSubject<RouteChanged>({ prevRoute: '/', currentRoute: '/' });

  constructor() {
  }
}

app.component.ts(你的根组件)

...

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
    private subscriptions = new Subscription();

    constructor(private eventsService: EventsService) {
            this.subscriptions.add(this.router.events
                .filter(event => event instanceof NavigationEnd)
                .pairwise()
                .subscribe(navigationEvents => {
                    const prevPage = <NavigationEnd>navigationEvents[0];
                    const currentPage = <NavigationEnd>navigationEvents[1];
                    this.eventsService.routeChanged.next(
                        { prevRoute: prevPage.urlAfterRedirects, currentRoute: currentPage.urlAfterRedirects });
                }));
        }

    ngOnDestroy(): void {
        this.subscriptions.unsubscribe();
    }

    ...
}

你的目标,route.ts

...
constructor(private eventsService: EventsService) {
    this.subscriptions.add(this.eventsService.routeChanged.subscribe((routeChanged) => {
        // use routeChanged.prevRoute and routeChanged.currentRoute here...
    }));
}

附:在服务中使用BehaviorSubjectReplaySubject非常重要,以便在页面加载后子组件订阅时获取正确的先前路由事件。


4
投票

答案已经给出:当组件为其注册时,已经引发了NavigationEnd事件。我不喜欢“Dimitar Tachev”的想法,通过在主题中代理这些事件来创建一种解决方法。在我的情况下,解决方案是:

  1. 让Component像以前一样订阅NavigationEnd事件。
  2. 使组件从ngOnInit方法中注入的Route对象加载初始状态。

最后,另一种解决方案是将订阅路由更改事件移动到组件的构造函数中。


3
投票

原因是导航事件发生时您的组件尚不存在。

创建一个注入app.component.ts的全局服务,并将其注入您的组件。

在服务上创建'helper'可观察对象。

// RouterEventsService.ts 
navigationStart$ = this.router.events.pipe(filter((e): e is NavigationStart => e instanceof NavigationStart));
navigationEnd$ = this.router.events.pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd));

navigationEndReplay$ = this.navigationEnd$.pipe(shareReplay(1));

在服务的构造函数中,您必须只订阅navigationEndReplay$事件。这意味着稍后在您的组件中,您可以订阅它并获取缓存的最新结束事件。

// RouterEventsService.ts constructor
this.routerEvents.navigationEndReplay$.subscribe();   // note: unsubscribe in app.component not needed

然后你可以在你的组件中使用routerEvents.navigationEndReplay$,它会在组件初始化后立即触发。你可以在你的构造函数,ngOnInitngAfterContentInit等中使用它。

最好保持navigationEnd$navigationEndReplay$明确。


2
投票

pairwise排放第二次和随后的排放(http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-pairwise

所以设置初始值很重要,例如:

this.router.events
  .startWith(new NavigationEnd(0, '/', '/'))
  .filter(e => e instanceof NavigationEnd)
  .pairwise()
  .subscribe((e) => {
      console.log(e);
  });

-1
投票

我只是偶然发现了相同的问题,并找到了原因:订阅路由器事件的服务从未由依赖注入器实例化,因为服务未在该路由注入。

服务似乎只是在某个地方注入时才会被实施。

因此,如果调用了整个代码(而不是事件),请检查您的第一条路线。

© www.soinside.com 2019 - 2024. All rights reserved.