本文轉載自: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
.
那麼這兩種傳參方式的關係和區別是啥?我們該如何在正確的場景使用這正確的方法?來研究研究。
paramMap
一個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
方法只會調用一次,而如果檢測到路由相同而參數不同時,是不會重新初始化組件的。
queryParamMap
一個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')); |
共同的api
- has(name) 如果參數名位於參數列表中,就返回 true 。
- get(name) 如果這個 map 中有參數名對應的參數值(字符串),就返回它,否則返回 null。如果參數值實際上是一個數組,就返回它的第一個元素。
- getAll(name) 如果這個 map 中有參數名對應的值,就返回一個字符串數組,否則返回空數組。當一個參數名可能對應多個值的時候,請使用 getAll。
- keys 返回這個 map 中的所有參數名組成的字符串數組。
paramMap和queryParamMap的最大的區別就是,paramMap是針對於當前url,哪怕是當前url的子頁面也無法獲取到當前頁面的參數。而queryParamMap是對所有路由都有效的查詢參數,在使用上需要應對不同情況進行選擇。一般使用都是針對於當前路由的,需要全局都有效的很少情況,所以一般還是使用paramMap,特殊情況採用queryParamMap。