订阅Angular 2中的route params和queryParams

时间:2016-11-19 23:56:08

标签: angular rxjs

我已设置以下路由系统

export const MyRoutes: Routes = [
    {path: '', redirectTo: 'new', pathMatch: 'full'},
    {path: ':type', component: MyComponent}
];

并拥有以下导航系统

goToPage('new');
goToPageNo('new', 2);

goToPage(type) {
    this.router.navigate([type]);
}
goToPageNo(type, pageNo) {
    this.router.navigate([type], {queryParams: {page: pageNo}});
}

示例网址看起来像这样

  

http://localhost:3000/new

     

http://localhost:3000/new?page=2

     

http://localhost:3000/updated

     

http://localhost:3000/updated?page=5

有时他们有可选 queryParams (页面)

现在我需要阅读 route params和queryParams

ngOnInit(): void {
    this.paramsSubscription = this.route.params.subscribe((param: any) => {
        this.type = param['type'];
        this.querySubscription = this.route.queryParams.subscribe((queryParam: any) => {
            this.page = queryParam['page'];
            if (this.page)
                this.goToPageNo(this.type, this.page);
            else
                this.goToPage(this.type);
        });
    });
}

ngOnDestroy(): void {
    this.paramsSubscription.unsubscribe();
    this.querySubscription.unsubscribe();
}

现在这没有按预期工作,访问没有queryParams的页面,然后我访问一个查询参数页面" goToPageNo"多次调用,因为我在route params中订阅了queryParams。

我查看了Angular 2文档,他们没有任何示例或代码同时实现对路由参数和queryParams 的订阅。

有什么方法可以做到这一点吗?有什么建议吗?

9 个答案:

答案 0 :(得分:42)

我通过在订阅前使用Observable.combineLatest组合observable来设法获得queryParams和Params的单一订阅。

例如

var obsComb = Observable.combineLatest(this.route.params, this.route.queryParams, 
  (params, qparams) => ({ params, qparams }));

obsComb.subscribe( ap => {
  console.log(ap.params['type']);
  console.log(ap.qparams['page']);
});

答案 1 :(得分:12)

对于Angular 6 +

import { combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';

...

combineLatest(this.route.params, this.route.queryParams)
    .pipe(map(results => ({params: results[0].xxx, query: results[1]})))
    .subscribe(results => {
        console.log(results);
    });

xxx来自您的路线

{path: 'post/:xxx', component: MyComponent},

答案 2 :(得分:8)

迟到的答案,但另一个解决方案: 我没有订阅params和queryparams,而是订阅了路由器上的NavigationEnd事件。仅触发一次,并且快照上都有params和queryparams :(角度4的示例)

this.router.events.filter(event=>event instanceof NavigationEnd)
   .subscribe(event=>{
       let yourparameter = this.activatedroute.snapshot.params.yourparameter;
       let yourqueryparameter = this.activatedroute.snapshot.queryParams.yourqueryparameter;
   });

关于取消订阅:是的,确实路由params,queryParams或导航事件订阅被路由器自动取消订阅,但有一个例外:如果您的路由有子节点,当在子节点之间导航时,不会发生取消订阅。只有当您离开父路线时才会离开!

E.g。我有一个标签作为子路线的情况。在第一个选项卡组件的构造函数中订阅路径参数以检索数据。每次我从第一个选项卡导航到第二个选项卡,然后再添加另一个订阅,从而导致请求数量相乘。

答案 3 :(得分:1)

使用<header> <img src={nicklogo} class="logo" alt="logo" /> <div class="center"> <ul> <li>Me</li> <li>Projects</li> <li>Skills</li> </ul> </div> </header>

中的ActivatedRouteSnapshot

ActivatedRoute界面具有ActivatedRouteSnapshotparams属性,您可以同时获取这两个值。

queryParams

编辑:正如OP所述,我们只用这种技术得到参数的初始值。

示例Plunker

答案 4 :(得分:1)

使用combineLatest提出的解决方案无法正常工作。在第一个路由更改之后,每次paramqueryParam值更改时,您都会得到一个事件,这意味着当一个更改但另一个没有更改时,您将处于中间状态。

@rekna的解决方案对我来说很有效,除了我的应用程序首次加载时没有收到事件,所以这是我对@rekna的解决方案的修改:

this.routeUpdate(this.activatedRoute.snapshot);
this.routeSubscription = this.router.events
  .pipe(filter(event => event instanceof NavigationEnd))
  .subscribe(event => this.routeUpdate(this.activatedRoute.snapshot));

routeUpdate是执行所需参数处理的一种方法。

答案 5 :(得分:1)

Shifatul 的回答扩展到......

  • Angular 9+(对 combineLastest 使用数组)和
  • 更简单的语法(使用 typescript 数组参数分解):
import { combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';

// ...

combineLatest([this.route.params, this.route.queryParams])
    .subscribe(([params, queryParams]) => {
        console.log("your route data:", params, queryParams);
    });

答案 6 :(得分:0)

我认为您应该使用zip运算符https://www.learnrxjs.io/operators/combination/zip.html

因为如果您使用CombineLatest并更改url参数或查询参数,则可以通过新的查询参数和旧的url参数获得价值。

网址,例如:

http://localhost/1?value=10

http://localhost/2?value=20

http://localhost/3?value=30

答案 7 :(得分:0)

另一种方法(在Angular 7及更高版本上)是订阅可观察到的ActivatedRoute网址,并使用“ withLatestFrom”获取最新的paramsMap和queryParamsMap。似乎已在可观察到的url发出之前设置了参数:

this.route.url.pipe(
  withLatestFrom(this.route.paramMap, this.route.queryParamMap)
).subscribe(([url, paramMap, queryParamMap]) => {
  // Do something with url, paramsMap and queryParamsMap
});

https://rxjs-dev.firebaseapp.com/api/operators/withLatestFrom

https://angular.io/api/router/ActivatedRoute

答案 8 :(得分:0)

按照 Shifatul 的回答,这假设对 observables 的工作同时改变并且只触发一次:

import { combineLatest } from 'rxjs';
import { map, debounceTime } from 'rxjs/operators';

...

combineLatest(this.route.params, this.route.queryParams)
    .pipe(map(results => ({params: results[0].xxx, query: results[1]})), debounceTime(0))
    .subscribe(results => {
        console.log(results);
    });