Angular PR

【Angular】5分でわかるRouterでSPAを作るための必須知識

【Angular】5分でわかるRouterでSPAを作るための必須知識
記事内に商品プロモーションを含む場合があります

こんにちは!

今、モダンWebアプリケーション開発の必須スキルとなっているAngularのRouter。

Angularのルーティングって何だろう?難しそう…
SPAって言われてもイマイチピンとこない…
ルーティングの基本は理解したいけど、どこから手をつければいいの?

もしかすると、そんな疑問や不安を抱えているかもしれませんね。

この記事では、AngularのRouterについて、基本的な概念から実装方法、応用テクニックまでを初心者にもわかりやすく解説していきます。

この記事は、以下のような方におすすめです。

この記事はこんな人におすすめ!
  • Angularを使い始めたばかりで、ルーティングについて知りたい方
  • SPAの仕組みやルーティングの基本を理解したい方
  • AngularのRouterの基本から応用までを学びたい方
  • 実際のプロジェクトでルーティングを実装する必要がある方

この記事を読めば、AngularのRouterの基本が理解できるだけでなく、自分のプロジェクトに実際に実装できるようになるでしょう。さらに、より高度なルーティング機能も使いこなせるようになります。

「Angularのルーティングを理解したい!」「SPAの開発をスムーズに進めたい!」とお考えの方は、ぜひ最後まで読んでください。

それでは、順を追って詳しく見ていきましょう!

AngularのRouterとは?その魅力と重要性

まず最初に、AngularのRouterとは何か、なぜこれが重要なのかについて理解しましょう。

SPAとAngularのRouterの関係

SPAとは「Single Page Application(シングルページアプリケーション)」の略で、ページ遷移の度にサーバーから新しいHTMLを取得するのではなく、最初に必要なリソースを読み込んだ後は、JavaScriptを使って動的にページの内容を書き換える仕組みのアプリケーションです。

Routerは、このSPAの中でページ遷移を実現するための機能を提供します。URLが変わっても実際にはページ全体を再読み込みすることなく、表示するコンポーネントを切り替えることで、あたかも別のページに移動したかのような体験を提供します。

AngularのRouterの重要性

Routerを使うことで、以下のようなメリットがあります。

UXの向上
ページ遷移が高速で、アプリケーションの応答性が向上します。
効率的なリソース管理
必要なデータだけを取得するため、通信量を削減できます。
状態管理の容易さ
URL管理により、アプリケーションの状態をURLに反映できます。
モジュール分割と遅延読み込み
必要なモジュールだけを必要なタイミングで読み込めます。

これらのメリットにより、よりユーザーフレンドリーで高速なウェブアプリケーションを構築することができます。

AngularのRouterの基本的な仕組み

Routerがどのように動作するのか、その基本的な仕組みを見ていきましょう。

ルーティングの基本概念

Routerの動作は、次の3つの要素から成り立っています。

Routes
URLパスとそれに対応するコンポーネントのマッピングを定義します。
Router Outlet
コンポーネントが表示される場所を指定するためのプレースホルダです。
Router Links
ユーザーがクリックして別のビューに移動するためのリンク要素です。

これらの要素を組み合わせることで、ユーザーが異なるページ間を移動する体験を作り出します。

ルートの定義方法

ルートの定義は、Routes型の配列として行います。各ルートは、pathとコンポーネントのマッピングを示すオブジェクトです。

import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
import { ContactComponent } from './contact/contact.component';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
  { path: '**', redirectTo: '' } // ワイルドカードルート(存在しないパスの場合)
];

上記の例では、ルートパスに対応するHomeComponent、'about'パスに対応するAboutComponent、'contact'パスに対応するContactComponentを定義しています。最後の行は、定義されていないパスにアクセスした場合に、ルートパスにリダイレクトするためのワイルドカードルートです。

RouterModuleの設定

定義したルートは、RouterModule.forRoot()メソッドを使ってAngularに登録します。これは通常、AppModuleなどのルートモジュールで行います。

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

// 上記で定義したroutesを使用
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Router Outletの配置

ルートに対応するコンポーネントを表示する場所は、<router-outlet></router-outlet>というタグで指定します。これは通常、アプリのルートコンポーネント(AppComponent)のテンプレート内に配置します。

<!-- app.component.html -->
<header>
  <!-- ナビゲーションメニューなど -->
</header>

<main>
  <router-outlet></router-outlet>
</main>

<footer>
  <!-- フッターコンテンツ -->
</footer>

このように配置することで、選択されたルートに対応するコンポーネントが<router-outlet></router-outlet>の位置に表示されます。

AngularのRouterの基本的な使い方

Routerの基本的な仕組みを理解したところで、実際の使い方を詳しく見ていきましょう。

ナビゲーションリンクの作成

ユーザーがクリックして別のルートに移動できるようにするためには、routerLinkディレクティブを使用します。

<nav>
  <ul>
    <li><a routerLink="/">ホーム</a></li>
    <li><a routerLink="/about">会社概要</a></li>
    <li><a routerLink="/contact">お問い合わせ</a></li>
  </ul>
</nav>

現在アクティブなリンクをハイライト表示したい場合は、routerLinkActiveディレクティブを使用します。

<nav>
  <ul>
    <li><a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">ホーム</a></li>
    <li><a routerLink="/about" routerLinkActive="active">会社概要</a></li>
    <li><a routerLink="/contact" routerLinkActive="active">お問い合わせ</a></li>
  </ul>
</nav>

[routerLinkActiveOptions]="{exact: true}"は、パスが完全に一致する場合にのみアクティブクラスを適用するオプションです。これは特にルートパス(’/’)に対して重要です。

プログラムによるナビゲーション

テンプレート内のrouterLinkの代わりに、コンポーネントのTypeScriptコード内から、プログラムによってナビゲーションを行うこともできます。これにはRouterサービスを使用します。

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

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html'
})
export class LoginComponent {
  constructor(private router: Router) {}

  onLogin() {
    // ログイン処理...
    // 成功したらダッシュボードに移動
    this.router.navigate(['/dashboard']);
  }
}

上記の例では、ログイン処理が成功した後に、プログラムによってダッシュボードページに移動しています。

パラメータを使ったルーティング

実際のアプリケーションでは、ユーザーID、商品ID、記事IDなどのパラメータをURLに含めて、それに基づいて動的にコンテンツを表示したいことがよくあります。Routerでは、これをルートパラメータとして簡単に実現できます。

ルートパラメータの定義

ルートパラメータは、パスの一部として:paramNameの形式で定義します。

const routes: Routes = [
  { path: 'product/:id', component: ProductDetailComponent }
];

上記の例では、product/1product/2などのURLにアクセスすると、全てProductDetailComponentが表示されます。

ルートパラメータの取得

コンポーネント内でパラメータを取得するには、ActivatedRouteサービスを使用します。

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

@Component({
  selector: 'app-product-detail',
  templateUrl: './product-detail.component.html'
})
export class ProductDetailComponent implements OnInit {
  productId: string;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    // snapshotを使う方法
    this.productId = this.route.snapshot.paramMap.get('id');

    // または、Observableを使う方法(URLが同じコンポーネント内で変わる可能性がある場合)
    this.route.paramMap.subscribe(params => {
      this.productId = params.get('id');
    });
  }
}

snapshotは現在のルートの状態を一度だけ取得する方法で、paramMap.subscribeはルートパラメータの変更を監視し続ける方法です。同じコンポーネント内でパラメータが変わる可能性がある場合は後者を使用します。

パラメータを含むリンクの作成

パラメータを含むリンクを作成するには、配列記法を使用します。

<a [routerLink]="['/product', product.id]">{{ product.name }}</a>

または、プログラムからナビゲートする場合:

this.router.navigate(['/product', productId]);

ネストされたルーティング

複雑なアプリケーションでは、ルートが階層構造を持つことがあります。例えば、管理ダッシュボード内に複数のサブセクションがあるケースなどです。Routerでは、子ルートを使って簡単にネストされたルーティングを実現できます。

子ルートの定義

子ルートは、親ルートのchildrenプロパティとして定義します。

const routes: Routes = [
  {
    path: 'admin',
    component: AdminComponent,
    children: [
      { path: '', component: AdminDashboardComponent },
      { path: 'users', component: AdminUsersComponent },
      { path: 'products', component: AdminProductsComponent }
    ]
  }
];

この例では、/adminにアクセスするとAdminComponentが表示され、その中で/admin/users/admin/productsといった子ルートに応じたコンポーネントが表示されます。

子ルートの表示

子ルートに対応するコンポーネントを表示するためには、親コンポーネント(この例ではAdminComponent)のテンプレート内に<router-outlet></router-outlet>を配置する必要があります。

<!-- admin.component.html -->
<div class="admin-container">
  <nav>
    <ul>
      <li><a routerLink="./" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">ダッシュボード</a></li>
      <li><a routerLink="./users" routerLinkActive="active">ユーザー管理</a></li>
      <li><a routerLink="./products" routerLinkActive="active">商品管理</a></li>
    </ul>
  </nav>

  <div class="content">
    <router-outlet></router-outlet>
  </div>
</div>

このように、親コンポーネント内にも<router-outlet></router-outlet>を配置することで、ネストされたルーティングが実現できます。

ルートガードによるアクセス制御

多くのアプリケーションでは、特定のページへのアクセスを制限したい場合があります。例えば、管理者ページは認証済みユーザーにのみアクセスを許可したり、未保存のフォームがある場合に確認なしでページを離れるのを防止したりするケースです。

Routerでは、これらの要件を満たすための「ルートガード」という機能を提供しています。

主なルートガードの種類

ガードの種類 用途
CanActivate ユーザーがルートにアクセスできるかどうかを決定します
CanActivateChild 子ルートへのアクセスを制御します
CanDeactivate ユーザーが現在のルートから離れることができるかどうかを決定します(例:未保存の変更がある場合)
Resolve ルートがアクティブになる前にデータを取得します
CanLoad 遅延読み込みモジュールへのアクセスを制御します

認証ガードの実装例

以下は、ユーザーが認証済みであるかどうかをチェックするCanActivateガードの実装例です。

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    const isLoggedIn = this.authService.isLoggedIn();

    if (isLoggedIn) {
      return true;
    }

    // 未認証の場合はログインページにリダイレクト
    this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
    return false;
  }
}

ガードの適用

ガードをルートに適用するには、ルート定義にガードを追加します。

const routes: Routes = [
  { path: 'admin', component: AdminComponent, canActivate: [AuthGuard] },
  {
    path: 'settings',
    component: SettingsComponent,
    canDeactivate: [UnsavedChangesGuard]
  }
];

上記の例では、/adminへのアクセスにはAuthGuardが適用され、ユーザーが認証済みでない場合はアクセスが拒否されます。また、/settingsからの離脱にはUnsavedChangesGuardが適用され、未保存の変更がある場合は確認ダイアログが表示されます。

遅延読み込み(Lazy Loading)の実装

大規模なアプリケーションでは、すべてのコードを最初に読み込むと初期ロード時間が長くなり、ユーザー体験が低下する可能性があります。Routerの遅延読み込み(Lazy Loading)機能を使用すると、必要なモジュールだけを必要なタイミングで読み込むことができます。

遅延読み込みの利点

初期ロード時間の短縮
最初に必要なコードだけを読み込むため、アプリケーションの起動が高速化します。
リソースの効率的な利用
ユーザーが訪れないセクションのコードは読み込まれないため、メモリ使用量が減少します。
モジュール単位の独立性
機能ごとのモジュール分割がしやすくなり、コードの管理が容易になります。

遅延読み込みの設定

遅延読み込みを実装するには、まず機能ごとにモジュールを分割し、各モジュールに独自のルーティング設定を行います。

機能モジュールのルーティング設定:

// product-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ProductListComponent } from './product-list.component';
import { ProductDetailComponent } from './product-detail.component';

const routes: Routes = [
  { path: '', component: ProductListComponent },
  { path: ':id', component: ProductDetailComponent }
];

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

メインのルーティング設定で遅延読み込みを指定:

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

const routes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'products',
    loadChildren: () => import('./product/product.module').then(m => m.ProductModule)
  }
];

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

この設定により、ユーザーが/productsにアクセスしたときにのみ、ProductModuleが読み込まれます。

キャリア形成/給与還元
ひとつひとつ真摯に向き合う企業
ONE_WEDGE社員募集

株式会社 ONE WEDGEでは、新たな仲間を募集しています!

私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。

  • 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
  • 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇、有給6日取得で特別休暇付与)を完備!
  • 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
  • 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
  • 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
  • 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
  • ワークライフバランスを重視し、副業もOK!

株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!

ホームページ、採用情報は下記ボタンからご確認ください!

応募、ご質問など、LINEでお気軽にご相談ください♪

まとめ

ここまで、AngularのRouterについて詳しく解説してきました。改めて、重要なポイントをおさらいしましょう。

  • AngularのRouterは、SPAにおけるページ遷移を実現するための重要な機能です
  • Routes、Router Outlet、Router Linksが基本的な構成要素となります
  • パラメータを使ったルーティングで動的なコンテンツ表示が可能です
  • ネストされたルーティングで階層構造を持つ複雑なナビゲーションを実現できます
  • ルートガードを使ってページへのアクセス制御を行えます
  • 遅延読み込みを導入して、アプリケーションのパフォーマンスを向上させることができます

AngularのRouterは、モダンなウェブアプリケーション開発において不可欠なスキルです。この記事で紹介した基本的な概念と実装方法をマスターすれば、より複雑で高度なAngularアプリケーションを開発できるようになるでしょう。

Routerの魅力は、コードを少し書くだけで、複雑なナビゲーション要件を簡単に実装できる点にあります。この記事を参考に、ぜひあなたのAngularプロジェクトでRouter機能を活用してみてください!

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です