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

Dav*_*rre 18 angular2-routing angular

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

this.router.events
      .filter(e => e instanceof NavigationEnd)
      .pairwise().subscribe((e) => {
          console.log(e);
    });
Run Code Online (Sandbox Code Playgroud)

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

 router.events
  .filter(e => e instanceof NavigationEnd)
  .subscribe(e => {
    console.log(e);
 });
Run Code Online (Sandbox Code Playgroud)

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

Kur*_*gor 19

正如我所看到的,所有这些解决方案都中继到route.snapshot并尝试将 NavigationEnd 操作与它结合起来。但是,如果您尝试访问该页面 - 它不会被第一个NavigationEndby触发router.events。快照也会触发父路由,而不是子路由。所以首先你可以使用子路由,但它也不会像第一个那样被解雇......

this.router.events.pipe(
  filter((event) => event instanceof NavigationEnd),
  map(() => this.aRoute.snapshot),
  map((route) => {
    while (route.firstChild) {
      route = route.firstChild;
    }
    return route;
  })
)
Run Code Online (Sandbox Code Playgroud)

所以对我来说,在正确的当前路线上第一次开火的最佳解决方案是使用router.events+router.url一种类型NavigationEnd

 this.router.events
   .pipe(
      filter((event) => event instanceof NavigationEnd),
      startWith(this.router)
   )
   .subscribe((event: NavigationEnd) => {
     // there will be first router.url - and next - router events
 })
Run Code Online (Sandbox Code Playgroud)

  • 爱它!第二个解决方案有很大帮助,遗憾的是,默认情况下不会发出任何事件。 (2认同)
  • 第二个解决方案真的很有帮助!谢谢 (2认同)

Ben*_*ing 7

2019,这仍然是一个问题

以下是如何获取所有路由更改,包括子组件中的页面加载路由。

  import { filter } from 'rxjs/operators';

  constructor(
    private router: Router, 
    private route: ActivatedRoute
  ) {
    // First route event on load
    this.setFromSnapshot(this.route.snapshot);
    // Subsequent events after load
    this.router.events
      .pipe(filter(event => event instanceof ActivationStart))
      .subscribe((event:ActivationStart) => this.setFromSnapshot(event.snapshot));
  }

  setFromSnapshot(snapshot:ActivatedRouteSnapshot) {
    // Do something
  }

Run Code Online (Sandbox Code Playgroud)


Tek*_*mmy 6

已经给出了答案:组件注册时,已经引发了NavigationEnd事件。我不喜欢“ Dimitar Tachev”的想法通过通过主题代理这些事件来创建解决方法。就我而言,解决方案是:

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

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


Dim*_*hev 5

我有完全相同的情况,我发现在子组件的构造函数中使用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() {
  }
}
Run Code Online (Sandbox Code Playgroud)

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

你的目标,route.ts

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

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


kru*_*i86 5

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


Nor*_*alo -2

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

服务似乎只有在被注入某处时才会被实例化。

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