Angular 向任何组件报告当前路由和参数?

Angular report current route and params to any component?

我真的不知道为什么这这么难......为什么我们正式不应该关心路由组件内部以外的任何地方的路由......但是:

我正在尝试为我的header(和任何其他组件)编写一个服务,它可以知道当前的路由和参数。也很高兴知道当前加载的组件,但这不太重要。

我尝试了 this thread 的各种解决方案,最接近我的是 RoyiNamir 的释义,但正如您从附带的 stackblitz 中看到的那样,它只报告页面加载时的参数,而不是随后的尽管有订阅和 NavigationEnd 的存在,但导航(尽管在解释路由事件和 rxjs 方面我是公认的超级绿色)。

我也不确定如何在返回的 object 中传递当前路由以及参数。

代码:

import {Injectable}                              from '@angular/core';
import {ActivatedRoute, NavigationEnd, Router}   from "@angular/router";
import {Observable}                              from "rxjs";
import {first, filter, map, switchMap}           from "rxjs/operators";

@Injectable({providedIn: 'root'})
export class RouteService {
  constructor(
    private route: ActivatedRoute, 
    private router: Router
  ){}
  public getActivatedRouteParameter(): Observable<any>
  {
    let params
    params = this.router.events.pipe(
      filter(e => e instanceof NavigationEnd),
        map((): ActivatedRoute => {
          let route = this.route;
          while (route.firstChild)
              {
                  route = route.firstChild;
              }
          return route;
        }),
        filter((route: ActivatedRoute) => route.outlet === 'primary'),
        switchMap((route: ActivatedRoute) => route.paramMap) , first()
    );
    return params;
  }
}

Working stackblitz

如果你像这样修改 getActivatedRouteParameter 似乎工作正常:

public getActivatedRouteParameter(): Observable<any>
  {
    let params
    params = this.router.events.pipe(
      filter(e => e instanceof NavigationEnd),
        map((): ActivatedRoute => {
          let route = this.route;
          while (route.firstChild)
              {
                  route = route.firstChild;
              }
          return route;
        }),
        filter((route: ActivatedRoute) => route.outlet === 'primary'),
        switchMap((route: ActivatedRoute) => route.paramMap.pipe(first())) , /* first() */
        tap(console.log)
    );
    return params;
  }

switchMapfirst() 外部 添加它会导致 整个流 在第一次发射后完成,这将是一个空对象(因为 ActivatedRoute's properties are BehaviorSubjects):

function createActivatedRoute(c: ActivatedRouteSnapshot) {
  return new ActivatedRoute(
      new BehaviorSubject(c.url), new BehaviorSubject(c.params), new BehaviorSubject(c.queryParams),
      new BehaviorSubject(c.fragment), new BehaviorSubject(c.data), c.outlet, c.component, c);
}

通过将 first() 添加到 switchMap 的内部可观察对象,您不会得到重复项。否则你会得到重复的,因为在你的情况下,每个路由导航都将 使用相同的组件 (HomeComponent),这意味着它不会被破坏,所以 ActivatedRoute 将是相同的,它的可观察属性也是如此。

这也意味着内部 observable 不会完成,所以当 ActivatedRoute 被重用时,它会 update its BehaviorSubject instances.

...
    if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) {
      (<any>route.params).next(nextSnapshot.params);
    }
...

这发生在管道的早期, NavigationEnd 事件之前。

StackBlitz