Angularの画面遷移について


Angularの画面遷移について説明しようと思います。
画面遷移とは言えどもAngularはコンポーネントベースのもので、URLの切り替わり=ページの切り替わりではなく、コンポーネントの切り替わりというものになります。

目次

  • プロジェクトの作成
  • ルート設定
  • RouterLinkによる方法
  • RouterのnavigateByUrlによる方法
  • リンクを階層構造にする

プロジェクトの作成

terminal
% ng new app-routing --routing

app-routingはプロジェクト名 --routingはプロジェクトでルーティングを使用する場合につけるオプションです。

作成後

app
 |- app-routing.module.ts  ←ルーティングを司るモジュール
 |- app.component.css
 |- app.component.html
 |- app.component.spec.ts
 |- app.component.ts
 |- app.module.ts          ←機能を司るモジュール

これらがデフォルトで作成されます。

ルート設定

app.routing.moduleを編集します。

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

const routes: Routes = []; 

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

routing.moduleのデフォルトの状態です。
import { Routes, RouterModule } from '@angular/router';でroute機能をimportしています

routing.module.ts
const routes: Routes = [
  { path: '',component: hogeComponent, children: []}
];

上記のroutesの配列内に画面遷移の情報を入れていきます。

pathでパスの指定を行い、componentでそのパスを打ち込んだときに表示するcomponentを指定します。
childrenは階層構造の際に今のパスの次にパスを記述して、componentを切り替えたい、追加したい時に使用します。
基本の配列(routing.module.ts)の場合では起動した際にhogeComponentを表示させるという意味合いになります。childrenは指定がないので階層構造はなにもありません。

app.moduleでrouting.moduleのインポート

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';  //デフォルトでimportされている
import { AppComponent } from './app.component';
import { Hoge1Component } from './hoge1/hoge1.component';
import { Hoge2Component } from './hoge2/hoge2.component';

@NgModule({
  declarations: [
    AppComponent,
    Hoge1Component,
    Hoge2Component
  ],
  imports: [
    BrowserModule,
    AppRoutingModule  //デフォルトでimportされている
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

コンポーネントのview

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

<router-outlet></router-outlet>とあることで、pathのコンポーネントがここに表示されるようになります。
実際にやってみましょう。
先程のapp-routing.moduleの配列を下記のように変更してください

app-ruting.module.ts
const routes: Routes = [
  {path: 'hoge1', component: Hoge1Component},
  {path: 'hoge2', component: Hoge2Component}
];

localhost4200

urlに/hoge1を追加した場合

urlに/hoge2と追加した場合

これはタイトルですはapp.componentの中身でその下にhoge1.componenthoge2.componentが来るという形になります。下の画像でhoge1.componentとなっているところが<router-outlet>となっていて、URLが切り替わるごとにここが変わります。

リンクの挿入

今はURLを書き換えることでコンポーネントを切り替えるようにしていましたが、基本的にはリンクをクリックしてからのコンポーネント切り替えになりますので、それについて説明していきます。

切り替えの方法としては、HTMLに記述する方法(routerLink)とTypeScriptに記述していく方法(controller)があります

RouterLinkによる方法

こちらはHTMLにリンクを記述する形になります。通常のHTMLとは異なった記述になります。

app.component.html
<a routerLink="/hoge1">hoge1</a>
<a routerLink="/hoge2">hoge2</a>
<router-outlet></router-outlet>

hoge1用とhoge2用のリンクを作成します。

URLによってコンポーネントが遷移することを確認できました。

TypeScriptによる方法

HTMLのリンクをボタンにして表現する場合はTypeScriptに記述してやるのがいいです。
app.component.htmlのhoge2をボタンにしてみます

app.component.html
<a routerLink="/hoge1">hoge1</a>
<button (click)="toHoge()">hoge2</button>
<router-outlet></router-outlet>

HTMLに記述されたメソッドの処理をTypeScriptに記述します。

app.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router'; //←画面遷移ができるようRouterをインポートする

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'route-app';

  constructor (private router: Router) {

  }
  //クリックした時にURLに飛べるメソッドを作成  
  toHoge2(): void{
    this.router.navigateByUrl('/hoge2');  //navigateByUrlはRouterクラスのメソッド
  }
}


hoge2がボタンに切り替わり、押すとURLとコンポーネントが切り替わります。

これらの切り替わりは全て一つのページ内で行われています。

リンクを階層構造にする

今はapp.componentの下にhoge1とhoge2があります。
hoge1をクリックするとhoge3というリンクが表示されるようにします。
hoge1のリンクをクリックするとhoge3のコンポーネントに切り替わるため、app-routing.moduleのhoge1の下層にリンクを作成します

app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Hoge1Component } from './hoge1/hoge1.component';
import { Hoge2Component } from './hoge2/hoge2.component';
import { Hoge3Component } from './hoge3/hoge3.component';  //hoge3.compnent作成時に自動追加

const routes: Routes = [
  {
    path: 'hoge1',
    component: Hoge1Component,
    //ここから
    children: [                                 
      {path:'hoge3', component: Hoge3Component}  //子要素を作る。
    ]
    //ここまでを追加
  },
  {path: 'hoge2', component: Hoge2Component}     //子要素と見た目同じ
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
hoge1.component.html
<div>
  <a routerLink="/hoge1/hoge3">hoge3</a>
</div>

ブラウザは下記のようになりましたが、hoge3のコンポーネントが見つかりません。(なおhoge3のリンクはhoge1のコンポーネントです)

上のhoge1.component.htmlで<router-outlet>を記述していないからです。URLを変更しても、コンポーネントは表示されませんので追加しましょう。

hoge1.component.html
<div>
  <a routerLink="/hoge1/hoge3">hoge3</a>
</div>
<router-outlet></router-outlet>


hoge3のコンポーネントが表示されるようになりました。

まとめ

コンポーネント切り替えを行うには
routing.module
pathの指定とそのパスではどのコンポーネントを扱うかという指定を行う

html
aタグでリンク先のpathを指定
buttonタグではTypeScriptでRouterクラスからURLへ飛ぶ処理を記述する

RoutingにはLazyLoadingという遅延ロードと呼ばれるものがあるので、その説明もおこないます。
失礼します。