本文转载自:http://blog.tcs-y.com/2019/03/28/ng2-router-paramMap-queryParamMap/
使用angular的router.navigate()
方法进行跳转页面的时候,我们传值的方式有两种:
router.navigate(['/a', {code: '123'}])
。构造的链接为/a;code=123
.router.navigate(['/b'], {queryMap: {code: '123'}})
。构造的链接为:/b?code=123
.那么这两种传参方式的关系和区别是啥?我们该如何在正确的场景使用这正确的方法?来研究研究。
一个Observable
,其中包含一个由当前路由的必要参数和可选参数组成的map
对象。用这个map
可以获取来自同名参数的单一值或多重值。
首先要区分下必选参数和可选参数。这涉及到路由的定义
如何定义一个必选参数:
{ path: 'a/:id', component: APageComponent, }, |
上面这样就创建了一个包含必选参数id
的路由了,这个路由中的:id
等于是在路径中创建了一个空位,这个空位不补全是没法导航的:
this.router.navigate(['/a']); // 跳转错误,无效路由 this.router.navigate(['/a', 1]); // 正确跳转,跳转url为:xxx/a/1 |
可选参数是在导航期间传送任何复杂信息的理想载体,可选参数不涉及到模式匹配并在表达式上提供了巨大的灵活性。那如何传递一个可选参数:
this.router.navigate(['/a', {a: 1, b: 2}]); |
上面这种方式跳转的时候,会生成跳转链接:/a;a=1;b=2
,对于路由/a
来讲,对象里面的a
和b
是可选参数的key。这是通过js来跳转,同样的直接通过页面跳转可以直接写成:
<a [routerLink]="['/a', {a: 3, b=2}]">B page</a> |
具有同样的效果。
注意:这里数组里的对象只可以是一层,不可以多层。这里转换的方式为第一层对象的key,值会直接转为string。所以,如果是多层对象的话会直接转成[object object]
,其他比如null也会直接转换为字符串null
上面了解了必选参数和可选参数的声明和使用,页面跳转到对应的目标页面后我们需要去获得这些参数,这时候就需要用到paramMap
了。
首先它是一个Observable,那么我们可以通过Observable的方式来拿。
this.activateRouter.paramMap.pipe( switchMap(params => of(params.get('a'))) ).subscribe((data) => { console.log('a', data); }); |
ActivatedRoute.paramMap
属性是一个路由参数的可观察对象,当用户导航到这个组件时,paramMap会发射一个新的值,我们可以在ngOnInit
中订阅拿到我们的参数。
这里为什么要加switchMap
操作符?可以参考:rxjs操作符-switchMap.
当然,可以使用“快照”(snapshot)的方式获取参数:
this.activateRouter.snapshot.paramMap.get('a'); |
通过快照的方式获取的参数是不需要Observable时的一个简写。这种情况你要保证该url只会用一次(即不会发生从当前url导航到当前url的情况)。因为使用这种方式获取的参数是不会变动的,因为组件的ngOnInit
方法只会调用一次,而如果检测到路由相同而参数不同时,是不会重新初始化组件的。
一个Observable,其中包含一个对所有路由都有效的查询参数组成的map对象。用这个map可以获取来自查询参数的单一或多重值。
使用navigate
方法的第二个参数,来看看navigate
方法的定义:
navigate(commands: any[], extras?: NavigationExtras): Promise<boolean>; |
可以知道第二个参数是导航附加功能,里面有个参数queryParams
可以为我们的路由加上查询参数:
this.router.navigate(['/b', {a: 33], { queryParams: { code: 'bbb', } }); |
上面的例子里面,我们的跳转后的链接为:/b;a=33?code=bbb
,a=33
这个是可选参数,不用管,code=bbb
才是我们需要的查询参数。
和其他参数不同,查询参数是可以在当前url中全部有效(包括子页面、service等其他部分也可以获取到)。
还可以在导航之间保留查询参数:
// 比如当前的url是在/b;a=33?code=bbb this.router.navigate(['/a', 1], { queryParamsHandling: 'preserve', }); |
这样跳转后的链接为:/a/1?code=bbb
。可以看到查询参数被保留了。
查询参数有更强大的配置,具体可以参见类型定义:NavigationExtras
paramMap和queryParamMap的获取方式都一样,都可以通过Observable的方式和快照的方式进行获取,例如:
this.activateRouter.queryParamMap.pipe( switchMap(params => { return of(params.get('code')); }) ).subscribe((data) => { console.log('query', data); }); console.log('b page a query param', this.activateRouter.snapshot.queryParamMap.get('code')); |
paramMap和queryParamMap的最大的区别就是,paramMap是针对于当前url,哪怕是当前url的子页面也无法获取到当前页面的参数。而queryParamMap是对所有路由都有效的查询参数,在使用上需要应对不同情况进行选择。一般使用都是针对于当前路由的,需要全局都有效的很少情况,所以一般还是使用paramMap,特殊情况采用queryParamMap。