Angular paramMap、queryParamMap、snapShot該如何應用?

原文鏈接:http://blog.tcs-y.com/2019/03/28/ng2-router-paramMap-queryParamMap/

本文轉載自: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來講,對象裏面的ab是可選參數的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=bbba=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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章