新版Ionic 4在頁面瀏覽(navigation)機制方面加入了Angular Router,連帶頁面權限方面也可使用Router的CanActivate等機制進行控管;Ionic舊版的push/pop方式雖仍可使用,但預期未來應不會再支援。
新建使用Angular Router的Ionic 4專案
為了讓新建專案使用Angular Router,Ionic CLI 4版加入新選項--type=angular。新建專案時加入此選項,便會建立Angular Routing模組檔,內有瀏覽頁面相關設定,例如新建專案:
ionic start RoutingExample blank --type=angular則會建立模組檔: src/app/app-routing.module.ts,內有預設頁面瀏覽路徑設定:
const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', loadChildren: './home/home.module#HomePageModule' }, ];
<ion-app> <ion-router-outlet></ion-router-outlet> </ion-app><ion-router-outlet>指令在切換瀏覽頁面時,會將redirect, loadChildren, 或component指定的內容帶入。
新增頁面ionic g page與lazy loading
Ionic CLI 4版目前(4.1.2)使用ionic g page產生新頁面時,並未支援類似3版--no-module選項,所以,所有頁面都是lazy loading頁面,自成一個模組。在上述專案裡,加入兩個頁面list與detail(list將列出所有清單項目, 點選個別項目,則進入detail頁面顯示該項目),隨後執行之:
cd RoutingExample ionic g page list ionic g page detail ionic serve
新增頁面,都會產生自己的模組檔(.module.ts),頁面路徑也會加入app-routing.module.ts,如下圖所示:
自動產生module檔,也更新路徑設定(更新app-routing.module.ts) |
自動更新後的app-routing.module.ts,皆以loadChildren屬性設定新增頁面,於進入該頁面時,才會載入:
const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', loadChildren: './home/home.module#HomePageModule' }, { path: 'list', loadChildren: './list/list.module#ListPageModule' }, { path: 'detail', loadChildren: './detail/detail.module#DetailPageModule' }, ];
至於執行期間,上述Routes與主要元件的Router Tree,如下圖所示:
|
Router Tree。三個元件皆為lazy loading。no-name-route則是用redirectTo所設定的預設路徑 |
插播:ionic g service
Ionic CLI 4版已將provider正名為service。為了建立list, detail兩個頁面的內容,此處建立一資料服務,將資料內容定義於此,同時提供讀取清單內容與個別項目內容的功能:
HTML檔定義連結/TS檔以navigate()切換頁面
ionic g service services/datasrc/services/data.service.ts檔內先定義資料欄位介面Language,以方便存取資料內容:
export interface Language{ id:string, name:string, intro:string }接著,定義資料list為Language類型之陣列,同時提供讀取全部內容的getList()與讀取單一項目的getItem(id):
export class DataService { list:Language[]=[]; constructor() { this.list = [ {id:'0', name:'Java', intro:'擁有跨平台、物件導向、...'}, {id:'1', name:'JavaScript', intro:'基於原型、函式先行的語言...'}, {id:'2', name:'Python', intro:'屬於通用型程式語言...。'}, {id:'3', name:'C', intro:'具有高效、靈活、功能豐富、表達...'}, {id:'4', name:'Ruby', intro:'一種物件導向、命令式、函數...'}, ]; } getList() { return this.list; } getItem(id):Language{ return this.list.find(e=>{return e.id===id}); } }如此,ListPage與DetailPage便可使用此服務,讀取對應資料。
HTML檔定義連結/TS檔以navigate()切換頁面
app-routing.module.ts檔裡Routes每一個路徑的path,都可以直接用在HTML檔內,例如,設定在href屬性內,或是使用Angular Router定義的routerLink屬性:
<ion-button href="/list">前往清單</ion-button> <a routerLink="/list">清單頁面</a>如此,按下按鈕或點選連結,便會載入path對應的元件內容。而除了在頁面直接設定連結外,HTML檔內也可採用事件繫結(event binding),透過TS程式端呼叫Router提供的navigate(), navigateByUrl()等methods,前往其他頁面,例如HTML檔綁定click的事件處理器detail(item):
<ion-button (click)="detail(item)" slot="end">前往</ion-button>而在TS檔定義detail(item),前往其他頁面,如:
detail(item){ this.router.navigateByUrl(`/detail/${item.id}`); }或是
detail(item){ this.router.navigate(['/detail/${item.id}']); }
瀏覽動態url頁面與ActivatedRoute
有時候頁面的網址無法事先得知,例如清單有許多項目,而使用者未點選前,無從得知該瀏覽到哪一個項目對應的網址。此時,app-routing.module.ts內的路徑設定,便必須設定參數,例如:
const routes: Routes = [{ path: '', redirectTo: 'list', pathMatch: 'full' }, { path: 'home', loadChildren: './home/home.module#HomePageModule' }, { path: 'list', loadChildren: './list/list.module#ListPageModule' }, { path: 'detail/:id', loadChildren: './detail/detail.module#DetailPageModule' }, ];
'/detail/:id'路徑便是動態路徑,無法事先得知;而id則是路徑的參數。不同參數值,如'/detail/0'與'detail/1',便會顯示不同內容。
搭配Routes動態路徑的設定,目的路徑元件便需要從網址中,擷取出參數值。以'detail/:id'對應的detail元件為例,該元件必須使用ActivatedRoute服務,取出網址傳送過來的參數值(detail.page.ts):
... import { ActivatedRoute } from '@angular/router'; ... export class DetailPage implements OnInit { id:string; ... constructor( private route: ActivatedRoute, ... ) { } ngOnInit() { this.id = this.route.snapshot.paramMap.get('id'); ... } }
重點摘要
- Ionic CLI 4版加入新選項--type=angular
- 自動生成Angular Router設定檔: src/app/app-routing.module.ts
- Angualr Router指令<ion-router-outlet></ion-router-outlet>取代原先的<app-root>成為程式進入點
- ionic g page產生的頁面預設為lazy loading,在Routes裡路徑會設定為loadChildren
- 擷取動態網址參數,可利用ActivatedRoute服務的snapshot.paramMap.get()。
最後,本文使用工具的版本如下:
node: 10.9.0 npm: 6.4.0 ionic CLI: 4.1.2
沒有留言:
張貼留言