Angular 2 テンプレート構文

これまでの章で Angular のテンプレートについて触れてきましたが、この記事では Angular の構文の使い方について具体的に紹介します。

テンプレートはビューの役割を担っており、簡単に言えばユーザーに表示する部分です。

  • HTML
  • 補間式
  • テンプレート式
  • テンプレート文
  • バインディング構文
  • プロパティバインディング
  • HTML属性、class と style のバインディング
  • イベントバインディング
  • NgModel による双方向データバインディング
  • 組み込みディレクティブ
  • * と <template>
  • テンプレート参照変数
  • 入力および出力プロパティ
  • テンプレート式の演算子

HTML

HTML は Angular テンプレートの「言語」です。<script> 要素が無効になっている以外は、他の HTML 要素はすべてサポートされています。例:

<h1>私の最初の Angular アプリ</h1>


補間式

補間式の構文は次のとおりです:{{ ... }}。

補間式は、計算された文字列を HTML に挿入したり、プロパティ値として使用したりできます。

<h3> {{title}} <img src="{{imageUrl}}" style="height:30px"> </h3>

テンプレート式

{{ ... }}その中身は実際にはテンプレート式であり、Angular がそれを評価して文字列に変換して出力します。

次の例は2つの数値を加算するものです:

<!-- "The sum of 1 + 1 is 2" --> <p>The sum of 1 + 1 is {{1 + 1}}</p>

次を使用できますgetVal()この式の値を取得するには:

<div class="example"> <div class="example_code"> [mycode3 type="html"] <!-- "4" --> <p>{{1 + 1 + getVal()}}</p>

テンプレート式は JavaScript に似た言語で、多くの JavaScript 式はテンプレート式としても有効ですが、すべてが有効なわけではありません。

次の JavaScript 式は禁止されています:

  • 代入式(=,+=,-=...)
  • new 演算子
  • を含む;または'連結式
  • インクリメントおよびデクリメント操作(++と--) JavaScript の構文と異なる注目すべき点は次のとおりです:
  • ビット演算子はサポートされていません(|と&)
  • テンプレート式の演算子、たとえば|と?.などには、新しい意味が与えられています。

プロパティバインディング

テンプレートのプロパティバインディングは、ビュー要素のプロパティをテンプレート式に設定できます。

最も一般的なプロパティバインディングは、要素のプロパティをコンポーネントのプロパティの値に設定することです。次の例では、image 要素の src プロパティがコンポーネントの imageUrl プロパティにバインドされます:

<img [src]="imageUrl">

コンポーネントが isUnchanged(未変更)のときにボタンを無効にします:

<button [disabled]="isUnchanged">ボタンは無効です</button>

ディレクティブのプロパティを設定します:

<div [ngClass]="classes">[ngClass] は classes プロパティにバインドされます</div>

カスタムコンポーネントのプロパティを設定します(これは親子コンポーネント間の通信における重要な方法です):

<user-detail [user]="currentUser"></user-detail>

HTML属性(Attribute)、class と style のバインディング

テンプレート構文は、プロパティバインディングがあまり適さないシナリオ向けに、特別な単方向データバインディング形式を提供します。

属性(Attribute)バインディング

要素にバインドできるプロパティがない場合は、HTMLタグ属性(Attribute)バインディングを使用します。

ARIA、SVG、table の colspan/rowspan などの属性(Attribute)を考えてみてください。これらは純粋な属性であり、バインドできる対応するプロパティがありません。

次の例ではエラーが発生します:

<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>

次のエラーが発生します:

Template parse errors:
Can't bind to 'colspan' since it isn't a known native property

模板解析错误:不能绑定到'colspan',因为它不是已知的原生属性

ヒントに記載されているように、<td>要素にはcolspanプロパティがありません。ただし、補間式とプロパティバインディングは設定できるのはプロパティではなく Attribute です。したがって、同様の Attribute を作成してバインドするには HTMLタグ Attribute バインディングが必要です。

HTMLタグ属性バインディングは構文上プロパティバインディングに似ていますが、角括弧内の部分は要素のプロパティ名ではなく、attr. プレフィックスと HTMLタグ属性名から構成され、文字列に評価される式によって HTMLタグ属性の値を設定します。例:

<table border=1> <tr><td [attr.colspan]="1 + 1">One-Two</td></tr> <tr><td>Five</td><td>Six</td></tr> </table>

CSSクラスバインディング

CSSクラスバインディングを使用すると、要素の class 属性に CSS クラス名を追加したり削除したりできます。

CSSクラスバインディングは構文上プロパティバインディングに似ています。ただし、角括弧内の部分は要素のプロパティ名ではなく、class プレフィックス、その直後のドット (.)、そして CSS クラス名で構成されます。最後の2つの部分は省略可能です。例:[class.class-name] 。

次の例は、CSSクラスバインディングを使用して "special" クラスを追加および削除する方法を示しています:

<!--標準的な HTML スタイルクラスの設定--> <div class="bad curly special">Bad curly special</div> <!--バインディングによるスタイルクラスのリセットまたは上書き--> <div class="bad curly special" [class]="badCurly">Bad curly</div> <!--プロパティ値によって special スタイルクラスを追加または削除する--> <div [class.special]="isSpecial">このスタイルは特別です</div>

スタイルバインディング

スタイルバインディングを使用すると、インラインスタイルを設定できます。スタイルバインディングは構文上プロパティバインディングに似ていますが、角括弧内の部分は要素のプロパティ名ではなく、style. に続いて CSS スタイルのプロパティ名が含まれます。例:[style.style-property]。

<button [style.color] = "isSpecial ? 'red': 'green'">赤</button> <button [style.background-color]="canSave ? 'cyan': 'grey'" >保存</button> <!--単位付きのスタイルバインディング--> <button [style.font-size.em]="isSpecial ? 3 : 1" >大</button> <button [style.font-size.%]="!isSpecial ? 150 : 50" >小</button>

スタイルプロパティはケバブケース(font-size)でも、キャメルケース(fontSize)でも指定できます。


イベントバインディング

イベントバインディングでは、Angular はキーボードイベント、マウスイベント、タッチイベントなどのユーザーアクションを監視することで、ビューターゲットからデータソースへの対応するデータフローに応答します。

イベントバインディングの構文は、等号の左側の括弧内にあるターゲットイベントと右側の引用符内にあるテンプレート文で構成されます。

たとえば次の例は、イベントバインディングがボタンのクリックイベントをリッスンするものです。マウスをクリックするたびに、コンポーネントのonSave()メソッドが呼び出されます。

<button (click)="onSave()">保存</button>

括弧内の名前、たとえば (click) は、ターゲットイベントを示します。次の例では、ターゲットはボタンの click イベントです。

<button (click)="onSave()">Save</button>

on- プレフィックス形式を使用することもできます:

<button on-click="onSave()">On Save</button>

NgModel による双方向データバインディング

データ入力フォームを開発するとき、期待される結果は、コンポーネントのデータをフォームに表示できると同時に、ユーザーが変更したときにコンポーネントのデータを更新できることです。

次は、...を介して[(NgModel)]双方向バインディングを実現するものです:

<input [(ngModel)]="currentUser.firstName">

[] はコンポーネントからテンプレートへのデータフローを実現し、() はテンプレートからコンポーネントへのデータフローを実現します。この2つを組み合わせた [()] で双方向バインディングが実現されます。

プレフィックス形式の構文を使用します:

<input bindon-ngModel="currentUser.firstName">

組み込みディレクティブ

Angular の組み込みディレクティブには、NgClass、NgStyle、NgIf、NgFor、NgSwitch などがあります。

NgClass

NgClass にバインドすることで、CSS クラスを動的に追加または削除できます。

<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'" >この div は大サイズです。</div>

NgStyle

NgStyle は、key:value の制御オブジェクトにバインドする形式を通じて、多くのインラインスタイルを同時に設定できます。

setStyles() { let styles = { // CSS属性名 'font-style': this.canSave ? 'italic' : 'normal', // italic 'font-weight': !this.isUnchanged ? 'bold' : 'normal', // normal 'font-size': this.isSpecial ? '24px' : '8px', // 24px }; return styles; }

NgStyle プロパティバインディングを追加して setStyles を呼び出し、それに基づいて要素のスタイルを設定します:

<div [ngStyle]="setStyles()">この div のスタイルは italic、normal weight、extra large (24px) です。</div>

NgIf

NgIf ディレクティブを真値の式にバインドすると、要素とその子要素を DOM ツリーに追加できます。

<div *ngIf="currentUser">Hello,{{currentUser.firstName}}</div>

逆に、偽値の式にバインドすると、その要素と子要素が DOM ツリーから削除されます。例:

<!--isActiveの値がfalseであるため、User DetailはDOMツリー内に存在しません。--> <user-detail *ngIf="isActive"></user-detail>

NgSwitch

一連の可能な要素ツリーから条件に応じて1つを表示する必要がある場合、NgSwitchが必要です。Angularは選択された要素のみをDOMに追加します。例:

<span [ngSwitch]="userName"> <span *ngSwitchCase="'张三'">张三</span> <span *ngSwitchCase="'李四'">李四</span> <span *ngSwitchCase="'王五'">王五</span> <span *ngSwitchCase="'赵六'">赵六</span> <span *ngSwitchDefault>龙大</span> </span>

親ディレクティブであるNgSwitchスイッチ値を返す式にバインドします。この例ではその値は文字列ですが、任意の型の値にすることができます。親ディレクティブはNgSwitch一連の<span>子要素を制御します。それぞれの<span>spanは、一致する値を持つ式にアタッチされるか、デフォルトとしてマークされます。どの時点でも、これらのspanのうち最大でも1つだけがDOMに現れます。このspanの一致値がスイッチ値と等しい場合、Angular2はこの<span>をDOMに追加します。どのspanも一致しない場合、Angular2はデフォルトのspanをDOMに追加します。Angular2は他のすべてのspanを削除して破棄します。

互いに連携する3つのディレクティブ:

  • ngSwitch:スイッチ値を返す式にバインドします。
  • ngSwitchCase:一致する値を返す式にバインドします。
  • ngSwitchDefault:デフォルト要素をマークするための属性*注意:ngSwitchの前では使用しないでください*。

NgFor

、代わりにプロパティバインディングを使用してください。ただし、ngSwitchCaseとngSwitchDefaultの前には置く必要があります。

<div *ngFor="let user of users">{{user.fullName}}</div>

複数の項目からなるリストを表示する必要がある場合、このディレクティブが必要です。以下の例は、HTMLブロックにNgForを適用したものです。

<user-detail *ngFor="let user of users" [user]="user"></user-detail>

NgForはコンポーネント要素にも適用できます。例:

ngForディレクティブはオプションのindexインデックスをサポートし、反復中に0から配列の長さまで増加します。

<div *ngFor="let user of users; let i=index">{{i + 1}} - {{user.fullName}}</div>

NgForTrackBy

このindexはテンプレート入力変数を使ってキャプチャし、テンプレート内で適用できます。次の例では、indexをiという名前の変数にキャプチャしています。

ngForディレクティブは、特に大規模なリストではパフォーマンスが低下することがあります。1つのエントリに対する小さな変更、削除、追加でも、連鎖的なDOM操作を引き起こします。

たとえば、サーバーから連絡先リストを再取得してリフレッシュする場合、リフレッシュ後のリストには、以前に表示された連絡先の多く(すべてではないにしても)が含まれる可能性があります。しかしAngularの視点では、どれが以前から存在していたかを知ることができないため、古いリストをクリーンアップし、それらのDOM要素を破棄し、新しいDOM要素で新しいリストを再構築するしかありません。

trackByUsers(index: number, user: User){return user.id}

この問題を解決するには、追跡関数を使用してこの手間を回避できます。追跡関数はAngularに、「同じuser.idを持つ2つのオブジェクトは同じ連絡先である」ことを伝えます。例:

<div *ngFor="let user of users; trackBy:trackByUsers">({{user.id}}) {{user.fullName}}</div>

次に、NgForTrackByディレクティブをその追跡関数に設定します。


テンプレート参照変数

テンプレート参照変数

テンプレート参照変数は、テンプレート内のDOM要素またはディレクティブへの参照です。

これはネイティブDOM要素で使用でき、Angularコンポーネントにも使用できます。実際には、任意のカスタムWebコンポーネントと連携できます。

テンプレート参照変数は、同じ要素、兄弟要素、または任意の子要素内で参照できます。

<!--テンプレート参照変数の作成と使用に関する2つの例を示します。--> <input #phone placeholder="phone number"> <button (click)="callPhone(phone.value)">Call</button> <!--phoneはinput要素を参照し、`value`をイベントハンドラに渡します。--> <input ref-fax placeholder="fax number"> <button (click)="callFax(fax.value)">Fax</button>

faxはinput要素を参照し、`value`をイベントハンドラに渡します。

「phone」の(#)プレフィックスは、phone変数を定義することを意味します。