31
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

IonicAdvent Calendar 2018

Day 14

Ionic v4 (@ionic/angular)でのルーティングについて

Last updated at Posted at 2018-12-13

この記事は、Ionic Advent Calendar 2018の14日目の記事です。

はじめに

Ionic v4ではページの遷移の方法が変わり、各フレームワーク用のルーターを使えるようになります。

この記事では利用者の多いと思われる Angular Router でのルーティングについて解説します。

基本

ページ遷移の元となる部分に<ion-router-outlet>を設置します。このコンポーネントは@ionic/angular専用です。Angularの<router-outlet>と同等の機能に加え、画面遷移アニメーションの処理などが追加されています。

app.component.html
<ion-app>
  <ion-router-outlet></ion-router-outlet>
</ion-app>

ルーティングは下の様に、各pathに対応するcomponentを設定していきます。

app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { HomeComponent } from './home/home.component';
import { UserListComponent } from './user-list/user-list.component';
import { UserDetailComponent } from './user-detail/user-detail.component';

const routes: Routes = [
  { path: '/', component: HomeComponent },
  { path: '/users', component: UserListComponent },
  { path: '/users/:id', component: UserDetailComponent }
];

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

あとはこのモジュールをAppModuleにインポートすればOKです。

ページを遷移するときは、

  • routerLinkディレクティブ
  • Routerサービス
  • NavControllerサービス(Ionic独自)

のいずれかを使用します。

page1.component.html
<ion-header>
  <ion-toolbar>
    <ion-title>Page1</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
  <ion-button routerLink="/page2" routerDirection="forward">page2</ion-button>
  <ion-button (click)="gotoPage2ByRouter()">page2</ion-button>
  <ion-button (click)="gotoPage2ByNavCtrl()">page2</ion-button>
</ion-content>
page1.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { NavController } from '@ionic/angular';

@Component({
  selector: 'app-page1',
  templateUrl: 'page1.component.html',
  styleUrls: ['page1.component.scss'],
})
export class Page1Component {
  constructor(private router: Router, private navCtrl: NavController) {}

  // AngularのRouterで遷移
  gotoPage2ByRouter() {
    this.router.navigateByUrl('/page2');
    //this.router.navigate(['/page2']);
  }

  // IonicのNavControllerで遷移
  gotoPage2ByNavCtrl() {
    this.navCtrl.navigateForward('/page2');
  }
}

/page2/:idなどURLのパスにパラメータを渡す場合は↓のように書きます。

// AngularのRouterで遷移
gotoPage2ByRouter() {
  this.router.navigateByUrl(`/page2/${id}`);
  //this.router.navigate(['/page2', id]);
}

// IonicのNavControllerで遷移
gotoPage2ByNavCtrl() {
  this.navCtrl.navigateForward(`/page2/${id}`);
}

routerLinkディレクティブのrouterDirectionプロパティは@ionic/angular独自のもので、遷移時のアニメーションを指定できます。

<ion-button routerLink="/page2" routerDirection="forward">page2</ion-button>

なお、以下の値が設定可能です。

  • forward(進む:デフォルト)
  • back(戻る)
  • root(差し替え, アニメーションなし)
  • auto(自動)

遷移先のページで「戻る」ボタンを実装するときはion-back-buttonを使いましょう。

page2.component.html
<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button text="戻る" defaultHref="/page1"></ion-back-button>
    </ion-buttons>
    <ion-title>Page2</ion-title>
  </ion-toolbar>
</ion-header>

また、/users/:idのようなパラメータを取得する場合は、ActivatedRouteを使用します。

page2.component.ts
@Component({
  selector: 'app-page2',
  templateUrl: 'page2.component.html',
  styleUrls: ['page2.component.scss'],
})
export class Page2Component implements OnInit {

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    const id = this.route.snapshot.paramMap.get('id');
  }
}

応用

モジュールのLazy Loading

モジュールのLazy LoadingはWebアプリとして動かす場合は有用です。Ionic v3では@IonicPageデコレータを使ってLazy Loadingしていましたが、v4からはAngular Routerの機能を使って

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

const routes: Routes = [
  { path: '/', loadChildren: './home/home.module#HomeModule' },
  { path: '/users', loadChildren: './user-list/user-list.module#UserListModule' },
  { path: '/users/:id', loadChildren: './user-detail/user-detail.module#UserDetailModule' }
];

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

の様に書くとモジュールをLazy Loadingしてくれます。

モジュールのPreloading

Cordovaで動かす場合は既に必要なデータが端末にインストールされているため(ページ遷移をスムーズに行うためにも)事前に読み込みを完了していることが望ましいです。

かといって、せっかくLazy Loading対応させたルーティング設定を今から書き直すのもちょっと...という場合はRouterModule.forRoot()PreloadAllModulesを指定しましょう。

RouterModule.forRoot({ routes, preloadingStrategy: PreloadAllModules });

メニュー

ion-menuでメニュー画面を作り、コンテンツを表示する部分にion-router-outletを使います。

<ion-menu contentId="main">
  <ion-header>
    <ion-toolbar>
      <ion-title>メニュー</ion-title>
    </ion-toolbar>
  </ion-header>
  <ion-content>
    <ion-list>
      <ion-menu-toggle>
        <ion-item>メニュー1</ion-item>
        <ion-item>メニュー2</ion-item>
      </ion-menu-toggle>
    </ion-list>
  </ion-content>
</ion-menu>
<ion-router-outlet id="main"></ion-router-outlet>

ion-menuを使う場合はion-router-outletmain属性またはidの指定が必要です。
https://qiita.com/puku0x/items/a278e31d90164b535299

タブ

v4-beta.18から各タブがLazy Loadingできるようになりました。ルーティングの書き方は前述したLazy Loadingのものと同じで、v4-beta.17以前の名前付きion-router-outletと比べてシンプルになっています。

<ion-tabs>
  <ion-tab-bar slot="bottom">

    <ion-tab-button tab="home">
      <ion-icon name="home"></ion-icon>
      <ion-label>Home</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="about">
      <ion-icon name="information-circle"></ion-icon>
      <ion-label>About</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="contact">
      <ion-icon name="contacts"></ion-icon>
      <ion-label>Contact</ion-label>
    </ion-tab-button>

  </ion-tab-bar>
</ion-tabs>

↑HTML側はion-tab-buttontab属性に各タブのパスを書くだけです。

各タブのルーティングをchildrenに書いていきます。redirectToの部分は必須です。

const routes: Routes = [
  {
    path: '',
    redirectTo: '/tabs/home',
    pathMatch: 'full'
  },
  {
    path: 'tabs',
    component: TabsComponent,
    children: [
      {
        path: 'home',
        children: [
          {
            path: '',
            loadChildren: './home/home.module#HomeModule'
          }
        ]
      },
      ...
    ]
  }
];

タブ内でページ遷移する場合、v4-beta.17以前では親モジュール(<ion-tabs>のあるところ)にルーティングを書いていましたが、v4-beta.18以降は各タブのモジュールに書けばよくなったのでわかりやすくなりました。

contact-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { ContactComponent } from './contact.component';

const routes: Routes = [
  {
    path: '',
    component: ContactComponent 
  },
  {
    path: 'detail',
    loadChildren: './contact-detail/contact-detail.module#ContactDetailModule'
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class ContactRoutingModule {}

今後変更されそうな部分

ページ遷移時の引数

Angular v7.2でルーターによる遷移時に任意のデータを渡せるようになるそうです。

おわりに

v3までのPush/Popで遷移する方式と違い、v4は自分でルーティングを組む必要があるので敷居がちょっと上がった感じはありますが、Webアプリからスマホアプリ、PWAまでカバーできるのでIonicは魅力的なフレームワークです。

普段からSPA開発に慣れていて、スマホアプリへの展開も考えている場合などには良い選択肢になると思います。

AngularとIonic両方追いかけるのは大変ですが、是非とも使いこなせるようになりたいですね。

31
21
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?