Dev Study
← 解説「コンポーネント — UIの基本単位」に戻る

サンプルコードで身につける: コンポーネント — UIの基本単位

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1最小のコンポーネント

コンポーネントの最小構成は「selector(タグ名)」と「template(表示内容)」の2つだけです。クラスにデコレータを付けるとHTMLタグとして使える部品になる、という核の部分を示しています。どんなに複雑な画面部品も、出発点はこの形です。

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

// selector がHTMLタグ名、template が表示内容になる
@Component({
  selector: 'app-hello',
  template: '<p>はじめてのコンポーネント</p>',
})
export class HelloComponent {}

// 使う側のテンプレートに <app-hello /> と書くと、
// その場所に <p>はじめてのコンポーネント</p> が表示される

2複数の要素を持つテンプレート

templateには1つの要素だけでなく、HTMLのかたまりをそのまま書けます。「見出しと本文を持つカード」のように、意味のあるまとまりを1部品にするのがコンポーネント分割の基本です。実務のコンポーネントはほとんどがこうした複数要素のテンプレートを持ちます。

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

@Component({
  selector: 'app-profile-card',
  // テンプレートには複数の要素をまとめて書ける
  template:
    '<article>' +
    '  <h2>プロフィール</h2>' +
    '  <p>フロントエンドエンジニア。Angularを勉強中。</p>' +
    '</article>',
})
export class ProfileCardComponent {}

3styles でこの部品だけの見た目を持つ

stylesに書いたCSSは、このコンポーネントの中だけに効きます。他の場所に同じクラス名があっても影響し合わない「スタイルのカプセル化」がコンポーネントの大きな利点です。実務では部品ごとに見た目のルールを閉じ込めることで、CSSの予期せぬ衝突を防ぎます。

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

@Component({
  selector: 'app-notice',
  template: '<p class="notice">本日23時からメンテナンスを行います</p>',
  // styles はこのコンポーネントの中だけに効く
  styles: ['.notice { color: darkorange; font-weight: bold; }'],
})
export class NoticeComponent {}

// 別のコンポーネントに .notice クラスがあっても影響しない

4コンポーネントを入れ子にする

あるコンポーネントの中で別のコンポーネントを使うには、使う側の imports に登録してテンプレートにタグを書きます。「部品の中に部品を置く」というこの入れ子構造こそが、Angularで画面を組み立てる基本の形です。

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

@Component({
  selector: 'app-site-header',
  template: '<header><h1>マイショップ</h1></header>',
})
export class SiteHeaderComponent {}

@Component({
  selector: 'app-page',
  // 使いたいコンポーネントを imports に登録してタグで呼び出す
  imports: [SiteHeaderComponent],
  template: '<app-site-header /><main>本文エリア</main>',
})
export class PageComponent {}

5画面を意味のある部品に分割する

実務のページは「ヘッダー」「商品一覧」「フッター」のように意味のある単位へ分割し、親コンポーネントで組み立てます。各部品が別ファイルに分かれることで、修正の影響範囲が部品の中に閉じ、同じヘッダーを別ページでも再利用できます。実際のプロジェクトのトップページは、ほぼ必ずこういう構造になっています。

import { Component } from '@angular/core';
import { HeaderComponent } from './header.component';
import { ProductListComponent } from './product-list.component';
import { FooterComponent } from './footer.component';

// 商品ページを「ヘッダー・一覧・フッター」の3部品で組み立てる
@Component({
  selector: 'app-shop-page',
  imports: [HeaderComponent, ProductListComponent, FooterComponent],
  template:
    '<app-header />' +
    '<app-product-list />' +
    '<app-footer />',
})
export class ShopPageComponent {}