首页 文章

在Angular中获取路由参数的有效方法

提问于
浏览
0

如何更有效地使用路由器Observable?如果我需要加载单个路由参数(例如我们有一个像 /some-resource/:id 这样的路由),我需要订阅路由器事件,然后订阅路由参数以获取值 . 这需要两个订阅和两个取消订阅 .

我想要:

  • 减少样板代码

  • 使代码更具可读性

  • 摆脱订阅

Sample

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

如果由于某种原因组件未被angular销毁,但仍使用不同的路由param stackblitz示例加载,则需要事件订阅来刷新数据:https://stackblitz.com/edit/angular-router-basic-example-695kpb

3 回答

  • 1

    您可以使用激活的路线 .

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

    你可以使用采摘 . pluck('id')map(value => value.id) 基本相同 . 如果您忘记取消订阅可观察者,请忘记 . 您可以使用take until运算符执行此操作 .

    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

    只要没有人发布更好的解决方案,这是我的:

    我定义了 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();
      }
    }
    
  • 0

    试试这个:

    constructor(private route: ActivatedRoute) {}
    
    ngOnInit() {
        const id = this.route.snapshot.params['id'];
    }
    

相关问题