iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
1

Day 2 安裝 VSCode & firstApp 解析 中最後帶到了點擊 Tabs 然後載入不同的 Page,最主要就是因為我們有設置 Route 。

首先我先準備一個 SideMenu 範本的 Ioinc 專案

ionic start demo2 sidemenu

然後 ionic serve 啟動後! 下面就是該 APP 。

app.component.ts

他的 app.component.ts 主要做了顯示側欄選單。
appPages 變數是 menu 的 item,主要有 title、url、ico 三個欄位。
在 ngOnInit 的時候,依據 url 判斷哪個 item 被選到了。

import { Component, OnInit } from '@angular/core';

import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent implements OnInit {
  public selectedIndex = 0;
  public appPages = [
    {
      title: 'Inbox',
      url: '/folder/Inbox',
      icon: 'mail'
    },
    {
      title: 'Outbox',
      url: '/folder/Outbox',
      icon: 'paper-plane'
    },
    {
      title: 'Favorites',
      url: '/folder/Favorites',
      icon: 'heart'
    },
    {
      title: 'Archived',
      url: '/folder/Archived',
      icon: 'archive'
    },
    {
      title: 'Trash',
      url: '/folder/Trash',
      icon: 'trash'
    },
    {
      title: 'Spam',
      url: '/folder/Spam',
      icon: 'warning'
    }
  ];
  public labels = ['Family', 'Friends', 'Notes', 'Work', 'Travel', 'Reminders'];

  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar
  ) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
    });
  }

  ngOnInit() {
    const path = window.location.pathname.split('folder/')[1];
    if (path !== undefined) {
      this.selectedIndex = this.appPages.findIndex(page => page.title.toLowerCase() === path.toLowerCase());
    }
  }
}

app.component.html

ion-menu-toggle 元件中 ngFor appPages 列出所有的 item。
ion-item 元件中 routerDirection 就純粹是頁面改變的動畫而已,有這三種 back、(預設)forward、root。
ion-item 元件中 [routerLink] 就是要被開啟的連結或頁面。
ion-router-outlet 元件則是依造現在 route 的狀態去動態塞入元件。

<ion-app>
  <ion-split-pane contentId="main-content">
    <ion-menu contentId="main-content" type="overlay">
      <ion-content>
        <ion-list id="inbox-list">
          <ion-list-header>Inbox</ion-list-header>
          <ion-note>hi@ionicframework.com</ion-note>

          <ion-menu-toggle auto-hide="false" *ngFor="let p of appPages; let i = index">
            <ion-item (click)="selectedIndex = i" routerDirection="root" [routerLink]="[p.url]" lines="none" detail="false" [class.selected]="selectedIndex == i">
              <ion-icon slot="start" [ios]="p.icon + '-outline'" [md]="p.icon + '-sharp'"></ion-icon>
              <ion-label>{{ p.title }}</ion-label>
            </ion-item>
          </ion-menu-toggle>
        </ion-list>

        <ion-list id="labels-list">
          <ion-list-header>Labels</ion-list-header>

          <ion-item *ngFor="let label of labels" lines="none">
            <ion-icon slot="start" ios="bookmark-outline" md="bookmark-sharp"></ion-icon>
            <ion-label>{{ label }}</ion-label>
          </ion-item>
        </ion-list>
      </ion-content>
    </ion-menu>
    <ion-router-outlet id="main-content"></ion-router-outlet>
  </ion-split-pane>
</ion-app>

app-routing.module.ts

這邊最主要就是 Routes 的設置。
我們可以看到,path: 'folder/:id',是戴了一個 id 的參數,然後載入 folder.module。
而 folder.module 中其實就只有一個頁面 folder.page 而已。在 folder.page 的文字也只是從 id 去抽換而已。

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: '',
    redirectTo: 'folder/Inbox',
    pathMatch: 'full'
  },
  {
    path: 'folder/:id',
    loadChildren: () => import('./folder/folder.module').then( m => m.FolderPageModule)
  }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

原PO自己看過的 Route

第一個 path 為 '' ,redirectTo 直接重新導向指定的 path。
pathMatch 則是告訴 router 怎麼樣去查找 route 。 這邊的 full 就是比較完整的路徑。
pathMatch 還可能的值為 prefix,他會比較部分。

第二個 path 為 'test',他會直接載入 TestComponent 元件。

第三個 path 為 'folder/:id',延遲載入的方式。一般情況下,如果直接用第二個 component 的方式,在 Ionic 載入的時候,該元件也會直接被載入,但如果你的專案很大,元件很多,在一開始載入的時候就會一次全部載入,導致APP 啟動效率差。用 loadChildren: () => import('./folder/folder.module').then( m => m.FolderPageModule) 的作法就可以把 folder.module 跟 app.module 拆開,當我們連接到 path 為 'folder/:id' 的時候在載入 folder.module 該模組。

第四個 path 為 'system',則是巢狀的寫法,children 底下又有 user 跟 permission。
'system/user' 他會載入 user.module
'system/permission' 他會載入 permission.module

const routes: Routes = [
  {
    path: '',
    redirectTo: 'folder/Inbox',
    pathMatch: 'full'
  },
  {
    path: 'test',
    component: TestComponent
  },
  {
    path: 'folder/:id',
    loadChildren: () => import('./folder/folder.module').then( m => m.FolderPageModule)
  },
  {
    path: 'system',
    children: [
        {
            path: 'user',
            loadChildren: () => import('../system/user.module').then(m => m.UserPageModule)
        },
        {
            path: 'permission',
            loadChildren: () => import('../system/permission.module').then(m => m.PermissionPageModule)
        }]
  }
];

如何取得路由參數

主要就是使用 ActivatedRoute。
this.activatedRoute.snapshot.paramMap.get('id');

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-folder',
  templateUrl: './folder.page.html',
  styleUrls: ['./folder.page.scss'],
})
export class FolderPage implements OnInit {
  public folder: string;

  constructor(private activatedRoute: ActivatedRoute) { }

  ngOnInit() {
    this.folder = this.activatedRoute.snapshot.paramMap.get('id');
  }

}

如何轉跳不同的路由

在之前的例子,我們看到在元件上面加上 [routerLink]=['/tabs'] 的作法。
如果是執行事件之後,然後在轉跳呢?
主要就是使用 Router 。
this.router.navigate(['/tabs']);
帶參數
this.router.navigate(['/tabs'], { queryParams: { id: 1 } });

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-folder',
  templateUrl: './folder.page.html',
  styleUrls: ['./folder.page.scss'],
})
export class FolderPage implements OnInit {

  constructor(private router: Router) { }

  ngOnInit() {
    this.router.navigate(['/tabs']);
    this.router.navigate(['/tabs'], { queryParams: { id: 1 } });
  }
}

上一篇
安裝 VSCode & firstApp 解析
下一篇
Grid Menu
系列文
純粹沒有寫過行動,Ionic 學習中...30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言