🅰️

Angular 2のDocsをゆるく翻訳してみた

2021/07/04に公開

こんにちは、@armorik83 です。

明後日 2015 年 3 月 21 日はng-japanですね。私も出席します。500 名の参加枠はすでにキャンセル待ちとなっています。ng-japan は日本初となる Angular のカンファレンスで、これに先駆けて先日 3 月 5-6 日にng-conf 2015が開催され Angular 2 の様子が更に明らかになったことから、期待のカンファレンスと言えます。(TypeScript の@vvakame 先生もスピーカとして登壇されます! これは楽しみだ!)

今回は、2 日後に控えた ng-japan のための予習として、angular/angularリポジトリに公開されている Docs をゆるく翻訳していきます。時間的制約のため、忠実な翻訳ではないことをご了承ください。誤りがあれば指摘してください。

2015 年 3 月 19 日現在、参照した commit はe0710c4613#です。

README

Angular

Angular は、モバイル・デスクトップ用 Web アプリケーション開発のためのプラットフォームです。ここは Angular 2 の(JS 版、Dart 版両方の)リポジトリです。

Angular 2 は現在アルファプレビュー版です。プロダクション用途には Angular 1.X 系の使用を推奨します。

  • AngularJS: angular/angular.js.
  • AngularDart: angular/angular.dart.

core/00_index

概要

  • 全てのコンポーネントについて高いレベルの説明

訳注: 書きかけと思われます。

core/01_templates

Templates

Template とは、DOM イベントがコントローラ上のどのメソッドを呼び出すか、アプリケーションモデルを DOM にどのように投影するかを宣言的に記述するために、HTML に追加されるマークアップです。これらには Angular の核を成し、データ・バインディング、イベント・バインディング、テンプレートのインスタンス化を可能にするための構文が含まれています。

Template 構文の設計として、次のような性質があります。

  • すべてのデータ・バインディング式が簡単に識別できる。(つまり、値が文字列リテラルとして、または式として解釈されるべきかどうかが曖昧になることはありません。)
  • 全てのイベントとその文が、簡単に識別できる。
  • 全ての DOM インスタンス化の箇所が、簡単に識別できる。
  • 全ての変数宣言の箇所が、簡単に識別できる。

これらの性質は、Template が(IDE などの)ツールによる解析や人による推論が容易であると保証します。Directive が機能しているか、ランタイムについて考える必要はありません。*

訳注*: この辺りふわっとした翻訳です。

要約

下記は、Angular の Template がサポートする構文の種類を要約したものです。構文は、以降のセクションで詳しく説明されています。

  • テキストの挿入
  • プロパティの挿入
  • プロパティのバインド
  • イベントのバインド(イベント・バブリングしない)
  • イベントのバインド
  • 参照の宣言
  • インライン・テンプレート
  • 明示的テンプレート

訳注: 書きかけと思われます。

Property Binding

プロパティのバインドはアプリケーション・データモデルを UI にバインドする、Angular で最も一般的な構文です。バインディングは常に式を割り当てられているプロパティ名の形式をとります。

Where*:

  • some-elementは既存の DOM 要素とすることができます。
  • some-property[]またはbind-でエスケープ)はsome-elementのプロパティ名です。この場合ハイフンつなぎはキャメルケースsomePropertyに変換されます。
  • expressionは有効な式です。 (これは以下のセクションで定義されています)

例:

<div [title]="user.firstName">

上記の例では、div要素のtitleプロパティは、user.firstNameがその値を変更するたびに更新されます。

キーポイント:

  • バインディングは要素属性ではなく要素プロパティに対してです。
  • 誤ってtitle要素のリテラル式を読んでカスタム要素化することを防ぐために、title[]を追加し[title]とすることでエスケープされます。
  • 値のバインディング。(この場合user.firstNameは文字列リテラルとは見なされず、常に式となります)

注: Angular 1 と異なり、Angular 2 は要素の属性へのバインドではなく、要素のプロパティに対してバインドされます。これはより良い要素のカスタムを支援するため文字列以外の値のバインドを可能にするために行われます。

注: いくつかのエディタやサーバ側プリプロセッサは属性名を[]で囲むことについて支障が発生するおそれがあります。このため、Angular ではbind-プレフィックスを使用した正規バージョンもサポートしています。

訳注*: Where は適切な訳が思いつきませんでした。

String Interpolation

Property Binding は Angular がサポートする唯一のデータ・バインディングですが、便宜上手短に挿入する構文を備えています。

<span>Hello {{name}}!</span>

これは以下を簡略化したものです。

<span [text|0]=" 'Hello ' + stringify(name) + '!' ">_</span>

上記は'Hello ' + stringify(name) + '!'式を<span>textプロパティの 0 番目にバインドする、といいます。複数のtextノードがある、またはバインドするtextノードが最初のものでない場合、index が必要となります。

同様に、同じ規則は要素の属性内への挿入に適用されます。

<span title="Hello {{name}}!"></span>

これは以下を簡略化しています。

<span [title]=" 'Hello ' + stringify(name) + '!' "></span>

注: stringify()関数はnullundefinedを空文字列とし、引数を文字列に変換する、暗黙的な(つまり global で使える)ビルトイン関数です。

Local Variables

(未執筆)

Inline Templates

データ・バインディングは DOM プロパティの更新を認めますが、DOM 構造の変更は許可しません。DOM 構造を変更するには、子テンプレートを定義し、これらのテンプレートを View にインスタンス化することが必要です。View は DOM 構造変更の必要に応じて挿入、除去ができます。

Where:

  • templateは、子テンプレートを定義し、View(テンプレートのインスタンス)が挿入されるアンカーを指定します。テンプレートは、テンプレート内の現在の要素の変更をtemplate属性によって暗黙的に、または<template>要素によって明示的に定義することができます。明示的な宣言は長くなりますが、それは複数のルート DOM ノードを持つテンプレートを有することを可能にします。
  • テンプレートにはviewportが必要です。viewportは子 View がこの場所に挿入する必要がある場合、いつ、どの順序かを決定する責任があります。viewportは通常 1 つまたは複数のバインディングを備えており、template要素または属性上のいずれかのviewport-directive-bindingsまたはviewport-directive-microsyntaxとして表すことができます。詳細については Template Microsyntax を参照してください。

条件付きでインクルードされたテンプレートの例:

Hello {{user}}!
<div template="if: isAdministrator">
  ...administrator menu here...
</div>

上記の例では、子 View(子テンプレートのインスタンス)をルートビューに挿入する必要があるかどうかをif Viewport が決定します。if Viewport は、isAdministratortrueの場合に基づいてこの決定を行います。

上記は短い例なので、より明確にするために機能的に同一である標準的な形で書き換えてみましょう。

Hello {{user}}!
<template [if]="isAdministrator">
  <div>
    ...administrator menu here...
  </div>
</template>

注: Viewport のみテンプレート要素上に配置できます。(Decorator と Component には許可されません)

Template Microsyntax

しばしば、テンプレートのインスタンスの生成方法を制御するため、テンプレートに異なるバインディングの多くを符号化する必要があります。その一例はforeachです。

<form #foo=form>
</form>
<ul>
  <template foreach #person [in]="people" #i="index">
    <li>{{i}}. {{person}}<li>
  </template>
</ul>

Where:

  • foreachは、foreach ディレクティブを作動させます。
  • [in]="people"では foreach コントローラへのイテレート可能なオブジェクトをバインドします。
  • #personは foreach 各項の暗黙的な出力です。
  • #i=indexは変数iにインデックス値を出力します。

上記の例は明示的ですが非常にくどいです。このような理由から、ほとんどの状況で短いバージョンの構文が好ましいでしょう。

<ul>
  <li template="foreach; #person; in=people; #i=index;">{{i}}. {{person}}<li>
</ul>

各 Key-Value のペアは、template属性内ではkey=value;文に変換されることに注意してください。この構文は遥かに短いですが、より良い記法があります。更に記述を短縮できるように、ほとんどの;は省略可能であると分かります。

<ul>
  <li template="foreach #person in people #i=index">{{i}}. {{person}}<li>
</ul>

必要に応じて#の替わりにvarを使用でき、下記のようなforeachの推奨される microsyntax のために:を追加できます。

<ul>
  <li template="foreach: var person in people; var i=index">{{i}}. {{person}}<li>
</ul>

Directive 開発者が microsyntax を表現できるよう、フォーマットは意図的に自由に定義されています。次のコードは、より正式な定義について説明します。

expression: ...
local: [a-zA-Z][a-zA-Z0-9]*
internal: [a-zA-Z][a-zA-Z0-9]*
key: [a-z][-|_|a-z0-9]]*
keyExpression: key[:|=]?expression
varExport: [#|var]local(=internal)?
microsyntax: ([[key|keyExpression|varExport][;|,]?)*

Where*

  • expressionは Expressions セクションにて定義されている Angular 式です。
  • localはローカル変数の識別子です。
  • internalはエクスポート Directive のバインドのための内部変数名です。
  • keyは通常、特定の Directive を動作させるために使用する属性名です。
  • keyExpressionは式としてバインドされるプロパティ名です。
  • varExportは、さらにバインドのための変数としてディレクティブ内部状態のエクスポートを可能にします。内部名が指定されていない場合、エクスポートは、暗黙の変数になります。
  • microsyntaxでは、簡単な microsyntax 構文を構築することができます。

訳注*: 全体的に何言ってんのか全然分かりませんでした。

注: template属性はサブテンプレートを作成されているユーザーにそれを明確にするために存在しなければなりません。template属性によって開発者は instantiator directive の意味を理解せずとも推論できるはずで、体系に従っていきます。

Binding Events

イベントのバインディングは Angular コントローラへの DOM(または他のコンポーネント)からのイベントの接続を可能にします。

Where:

  • some-elementは既存の DOM 要素とすることができます。
  • some-property()またはbind-でエスケープ)はsome-elementのプロパティ名です。この場合ハイフンつなぎはキャメルケース someProperty に変換されます。
  • expressionは有効な式です。 (これは以下のセクションで定義されています)

デフォルトでは Angular はイベント対象の要素に対してのみ Listen し、イベントのバブリングは無視します。バブリングするイベント(子要素のクリックなど)の Listen については以下に示すように、バブリング・オプション( (^event)またはon-bubble-event)を使用します。

@Component(...)
class Example {
  submit() {
    // do something when button is clicked
  }
}

<button (click)="submit()">Submit</button>

この例では、Submitボタンをクリックすると、Angular はコントローラ上のメソッドsubmit()を呼び出します。

注: Angular 1 とは異なり、Angular 2 ではイベント・バインディングをディレクティブとしてではなくコアとして扱います。これはイベントの種類ごとにイベント・ディレクティブを作成する必要がないことを意味します。Angular 2 ではイベント名が事前に知られていなくても、カスタム要素のカスタム・イベントにバインドできるようになります。

Expressions, Statements and Formatters

Angular の Template にはデータ・バインディングのための式と、イベント・バインディングのための文が含まれています。式expressionsと文statementsは異なる意味を持っています。

Expressions

Expression は、プロパティへのバインドのためにのみ使用されます。Expression は、データがビューに反映する方法を表しています。Expression は副作用を持つべきでなく、冪等である必要があります。Angular で Expression を使用することができる場所の例を次に示します。

<div title="{{expression}}">{{expression}}</div>
<div [title]="expression">...</div>
<div bind-title="expression">...</div>
<div template="if: expression">...</div>

Expression は、あなたがアプリケーションを作成する際の言語に応じて表現が簡略化されています。(つまり JS ならば JS 構文とそのセマンティック、Dart ならば Dart 構文とそのセマンティックに従ってください)言語の式とは異なり、バインド用 Expression は、以下のように異なる挙動を示します。

  • 定義が必要: Angular 1 とは異なり、Angular 2 は定義されていないフィールドの参照でエラーを投げます。例えば、userは宣言済みでもnameプロパティを持たない場合、user.nameはエラーとなります。nameプロパティが未定義の場合は宣言し、null(または JS でのundefined)や空の文字列など、いくつかの値に設定しておく必要があります。これはテンプレート内エラーの早期検出を可能にするためです。
  • 安全な参照: user.nameという Expression において、usernullならば言語によるNullPointerExceptionが投げられますが、これとは対照的に Angular は黙ってusernullを無視します。View では、多くの場合データがバックエンドから到着するまで、多くのフィールドがnullになり待つ必要があるため、このようになっています。安全な参照は、View において非常に一般的です。
  • 単一の式: Expression は単一の文でなければなりません。(すなわち;が不要です)
  • 代入不可: Expression に代入を含めることはできません。
  • キーワード使用不可: Expression にvarifといったキーワードを含めることはできません。
  • Formatter: Angular の Expression はバインドした値を変換するため、Formatter に接続することができます。(Formatters を参照)

幾つかの Expression とその挙動の例:

このようなクラスがあったとします:

class Greeter {
  name:string;
}
  • name: Greeterクラスでのnameプロパティの値となります。
  • name.length: name文字列の長さとなるか、またはnameが未定義の場合null (Dart)やundefined (JS)となります。
  • foo: fooGreeterクラスで宣言されていないため、エラーが投げられます。
  • name=1: 代入は許可されません。
  • name; name.length: 複数の文は許可されません。

Statements

Statement は、イベント・バインディングのためだけに使用されます。Statement は、イベントに応じて動作するアクションが示されます。以下は Angular における Statement が記述できる場所の例です。

<div (click)="statements">...</div>
<div on-click="statements">...</div>

Statement は、あなたがアプリケーションを作成する際の言語のステートメントに似ています。(つまり Statement は、Dart や JS の構文、セマンティックに従います)ただし言語のステートメントとは異なり、Statement は、次のように異なる挙動をします。

  • 安全ではない参照: usernullなときのuser.verify()という式は、言語の中でも Statement の中でも、NullPointerExceptionを投げます。(これは Angular Expression の「安全な参照」とは対照的です)Expression 内では Angular がデータの遅延ロードに起因するnull参照から保護してくれますが、このような保護は Statement では必要とされず、むしろそのように保護することはタイプミスの検出を難しくするでしょう。
  • 数 Statement の指定可: Statement は複数の文から構成することができます。(doA(); doB()のように)
  • 代入可: イベントバインディングは副作用を持てるので、代入は許可されています。
  • キーワード使用不可: Expression にvarifといったキーワードを含めることはできません。
  • Formatter 不可: Formatter は値のバインドにのみ使用されます。

3 時間かけてここまでとなりました。(全ページなんて 1 日じゃ無理だ)Angular 2 のテンプレート文は結構変わることが事前に分かっていたため、英文斜め読みではなく逐一翻訳したことでかなり理解が深まりました。色んな意味で、ヤバい。

Docs の他のページは別の記事で投稿するかもしれないし、やらないかもしれない。それでは ng-japan で会いましょう。

Discussion