Angular でUI開発を成功させるための秘訣:コンポーネントとディレクティブのベストプラクティス
Angular コンポーネントとディレクティブの違い
コンポーネント は、UI の再利用可能なモジュールとして機能します。HTML テンプレート、TypeScript クラス、CSS スタイルシートを組み合わせることで、カプセル化された機能と視覚表現を持つ独立したブロックを作成できます。コンポーネントは、入力プロパティと出力イベントを介して他のコンポーネントと通信できます。
一方、ディレクティブ は、特定の機能や動作を DOM 要素に追加するために使用されます。構造ディレクティブ、属性ディレクティブ、装飾ディレクティブの 3 種類があります。
- 装飾ディレクティブ は、コンポーネントの機能を拡張するために使用されます。例えば、
@Input
ディレクティブは、コンポーネントのプロパティに値を受け渡すために使用できます。 - 属性ディレクティブ は、HTML 要素の属性を変更するために使用されます。例えば、
ngDisabled
ディレクティブは、入力フィールドを無効にするために使用できます。 - 構造ディレクティブ は、DOM 構造を操作するために使用されます。例えば、
*ngFor
ディレクティブは、ループを反復して DOM 要素を生成するために使用できます。
簡潔に言えば、コンポーネントは "レゴブロック" のようなもので、UI の構築に使用される基本的なモジュールです。一方、ディレクティブは "装飾品" のようなもので、コンポーネントに機能や動作を追加するために使用されます。
項目 | コンポーネント | ディレクティブ |
---|---|---|
役割 | UI の構築 | DOM 要素への機能追加 |
構造 | HTML テンプレート、TypeScript クラス、CSS スタイルシート | 単一の TypeScript クラス |
通信 | 入力プロパティと出力イベント | 属性とメソッド |
再利用性 | 高い | 中程度 |
複雑性 | 高い | 低い |
例
ボタンコンポーネントを作成することを考えてみましょう。このコンポーネントは、ラベル、クリックイベントハンドラー、スタイルを持つことができます。
<button [label]="label" (click)="handleClick()"></button>
// button.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-button',
templateUrl: './button.component.html',
styleUrls: ['./button.component.css']
})
export class ButtonComponent {
@Input() label: string;
@Output() click = new EventEmitter<void>();
handleClick() {
this.click.emit();
}
}
このコンポーネントを別のテンプレートで使用することができます。
<app-button label="クリック" (click)="onClick()"></app-button>
一方、ディレクティブは、ボタンコンポーネントに機能を追加するために使用することができます。例えば、ngStyle
ディレクティブを使用して、ボタンの色を動的に変更することができます。
<app-button label="クリック" [ngStyle]="{'background-color': color}"></app-button>
この例では、app-user
という名前のコンポーネントを作成します。このコンポーネントは、ユーザーの名前とメールアドレスを表示するテンプレートと、ユーザーデータを処理する TypeScript クラスで構成されています。
app-user.component.html
<div class="user">
<h2>{{ user.name }}</h2>
<p>{{ user.email }}</p>
</div>
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-user',
templateUrl: './app-user.component.html',
styleUrls: ['./app-user.component.css']
})
export class UserComponent {
@Input() user: { name: string; email: string };
}
<app-user [user]="user"></app-user>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
user = {
name: 'John Doe',
email: '[email protected]'
};
}
ディレクティブ例
この例では、highlight
という名前のディレクティブを作成します。このディレクティブは、要素に背景色を追加するために使用されます。
highlight.directive.ts
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[highlight]'
})
export class HighlightDirective {
@Input() highlightColor: string;
constructor(private el: ElementRef) { }
@HostListener('mouseenter') onMouseEnter() {
this.el.nativeElement.style.backgroundColor = this.highlightColor;
}
@HostListener('mouseleave') onMouseLeave() {
this.el.nativeElement.style.backgroundColor = '';
}
}
<p highlight highlightColor="yellow">このテキストは黄色になります。</p>
このコードを実行すると、highlight
ディレクティブが p
要素に適用され、マウスカーソルが要素の上を移動すると背景色が黄色になります。
- ディレクティブは、スコープ化されたコンテキストを提供しません。ディレクティブ内の変数と関数は、テンプレート内のどこからでもアクセスできます。
- コンポーネントは、テンプレート内でローカルスコープを持つスコープ化されたコンテキストを提供します。コンポーネント内の変数と関数は、そのコンポーネントテンプレート内でのみアクセスできます。
データバインディング
- ディレクティブは、
@Input
デコレータを使用して、ディレクティブとホストコンポーネント間でデータをバインドできます。ただし、@Output
デコレータを使用してイベントを発行することはできません。 - コンポーネントは、
@Input
と@Output
デコレータを使用して、コンポーネント間でデータをバインドできます。
ライフサイクル
- ディレクティブは、
OnInit
、OnChanges
、OnDestroy
などのライフサイクルフックも備えています。ただし、コンポーネントほど多くのライフサイクルフックはありません。 - コンポーネントは、
ngOnInit
、ngOnChanges
、ngOnDestroy
などのライフサイクルフックを備えています。これらのフックは、コンポーネントの作成、データの変更、破棄時に呼び出されます。
テンプレート
- ディレクティブは、テンプレートを持つことができません。ただし、ホストコンポーネントのテンプレートを操作するために使用できます。
- コンポーネントは、独自のテンプレートを持つことができます。このテンプレートは、HTML、CSS、および他のコンポーネントを組み合わせて構成できます。
スタイル設定
- コンポーネントは、独自の CSS スタイルシートを持つことができます。このスタイルシートは、コンポーネントテンプレートのみに適用されます。
Angular コンポーネントとディレクティブは、どちらも UI を構築するための強力なツールですが、それぞれ異なる役割と機能を持っています。コンポーネントは、再利用可能な UI モジュールを作成するために使用されるのに対し、ディレクティブは、既存のコンポーネントに機能を追加するために使用されます。
angular components angular-directive