Эффективный способ получить параметр маршрута в Angular - PullRequest
0 голосов
/ 20 сентября 2018

Как я могу более эффективно использовать Observables маршрутизатора?Например, если мне нужно загрузить один параметр маршрута (скажем, у нас есть маршрут типа /some-resource/:id), мне нужно подписаться на событие маршрутизатора, а затем на параметры маршрута, чтобы получить значение.Это требует двух подписок и двух отписок.

Я хотел бы:

  • Уменьшить шаблонный код
  • Сделать код более читабельным
  • Избавитьсяподписок

Пример

export class SomeComponent implements OnInit, OnDestroy {
  private routerSub: Subscription;
  private routeSub: Subscription;

  someResource: Observable<SomeResourceType>;

  constructor(private someService: SomeService,
              private route: ActivatedRoute,
              private router: Router) {
    this.routerSub = this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        this.routeSub = this.route.params.subscribe((params) => {
          if (params['id']) {
            this.someResource = this.someService.findById(params['id']);
            // will access the resource using async pipe later
          }
        });
      }
    });
  }

  ngOnInit(): void {
  }

  ngOnDestroy(): void {
    this.routerSub.unsubscribe();
    this.routeSub.unsubscribe();
  }
}

Подписка на событие необходима для обновления данных, если по какой-либо причине компонент не разрушен угловым, но все жезагружается с использованием другого примера стекаблика параметров маршрута: https://stackblitz.com/edit/angular-router-basic-example-695kpb

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Попробуйте это:

constructor(private route: ActivatedRoute) {}

ngOnInit() {
    const id = this.route.snapshot.params['id'];
}
0 голосов
/ 20 сентября 2018

Для этого вы можете использовать активированный маршрут.

constructor(route: ActivatedRoute) {
    this.id$ = route.params
        .pipe(pluck('id'));
}

Вы можете использовать pluck.pluck('id') в основном совпадает с map(value => value.id).Если вы не хотите иметь поток, но фактическое значение, вы можете сделать то же самое и подписаться на него.Но если вы это сделаете, не забудьте отписаться от заметки.Вы можете сделать это с оператором take to.

id;
private _destroyed$ = new Subject<any>();

constructor(route: ActivatedRoute) {
    route.params
        .pipe(
            takeUntil(this._destroyed$),
            pluck('id')
        ).subscribe(id => this.id = id);
}

ngOnDestroy() {
    this._destroyed$.next();
    this._destroyed$.complete();
}
0 голосов
/ 20 сентября 2018

Пока никто не публикует лучшее решение, вот мое:

Я определил RouterHelperService, что несколько упрощает этот процесс.Одна из проблем заключается в том, что если вы попытаетесь внедрить экземпляр ActivatedRoute непосредственно в своем сервисе, вам не хватит параметров, поэтому вам нужно передать его из компонента в сервис.

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

@Injectable({
  providedIn: 'root'
})
export class RouterHelperService {

  constructor(private router: Router) {
  }

  onNavigationEndReadParamByKey(route: ActivatedRoute, key: string): Observable<string> {
    return this.router.events.pipe(
      filter(event => event instanceof NavigationEnd),
      flatMap(() => {
        return route.params.pipe(
          filter(params => params[key]),
          map(params => params[key])
        );
      })
    );
  }
}

Таким образом, в моем компоненте я могу назвать его одним вызовом и одной подпиской.

export class SomeComponent implements OnInit, OnDestroy {
  private routeSub: Subscription;

  someResource: Observable<SomeResourceType>;

  constructor(private someService: SomeService,
              private route: ActivatedRoute) {
     this.routeSub = this.routerHelper.onNavigationEndReadParamByKey(this.route, 'id').subscribe((id) => {
        this.someResource = this.someService.findById(+id); //+id to convert it from a string to a number
     });
  }

  ngOnInit(): void {
  }

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