Angularチュートリアルをやってみて -2-

チュートリアルを一通りやってみたが、よく分からなかった。 理解を深めるために、やった内容を書き出してみる。
今回はデータバインディングの基本を復習する。

データバインディング

データバインディングは、コンポーネントとテンプレート(ビュー)を紐付ける仕組み。Angularのデータバインディング構文は、データの流れる方向によって、大きく4種類に分類できる。

No. データ方向 種類 記法
1 コンポーネント=>ビュー Interpolation(補間 {{...}}
2 コンポーネント=>ビュー プロパティ/属性バインディング [property]="Value"
3 ビュー=>コンポーネント イベントバインディング (event)="handler"
4 コンポーネント<=>ビュー 双方向バインディング [(target)]="Value"

チュートリアル内のヒーローエディタの章で使ったのは、1と4である。違いとしては、双方向でデータのやり取りができるかどうかである。双方向バインディングでは、コンポーネントのプロパティとテキストボックスを同期させることで、テキストボックスの更新により、プロパティ値に反映させることができる。

Interpolation(補間)構文

最も初歩的なバインド記法であるInterpolation(補間)は、 {{...}} で表現される。
サンプルコード

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

@Component({
  selector: 'my-app',
  template: `<h1>Hello {{name}}</h1>`,//--------------------2
})

export class AppComponent {
  name = 'Angular'//----------------------------------------1
}

1 で定義されたnameプロパティを 2{{name}}として参照している。

{{...}}式の注意点

1.利用できない演算子がある

主に副作用を伴う演算子は、{{...}}式では禁止されている。

2.グローバル名前空間のオブジェクトを参照できない

{{...}}式のコンテキストは、コンポーネントインスタンスである。window、Mathのようなグローバル名前空間上のオブジェクトに{{...}}式からアクセスすることはできない。

3.{{...}}式を利用する上でのガイドライン

  • 式が副作用を伴わないこと(=他の値に影響がでないこと)
  • 短時間で実行できること
  • シンプルであること
  • 同じ操作を何度実行しても同じ結果を返すこと

Angularでは、{{...}}式を何度も評価する。時間のかかる式は、そのままアプリの速度低下につながる可能性があるので、注意が必要。

「?.」演算子

{{...}}式だけで利用できる演算子に「?.」演算子がある。これはオブジェクトが空であるか判断し、空でない場合にだけプロパティにアクセスする。

双方向バインディング

コンポーネントクラスから画面へ、そして画面からコンポーネントクラスへのデータフローを作る。 <input>フォーム要素とプロパティとの間に双方向データバインディングの設定をする。サンプルコードは以下のようになる。

<!--app.component.html-->
<input type="text" [(ngModel)]="text" />

<label>{{text}}</label>
//app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    public text: string = "hoge";
}

[(ngModel)]は双方向データバインディング構文。
ngModelはデフォルトでは使用できない。理由は、オプションのFormsModuleに属しており、使用するにはモジュールをオプトインする必要がある。

//app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';// <---追加

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule// <---追加
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

まとめ

[(ngModel)]を使い、双方向データバインディングをすると、データのやり取りできる。単純に参照するだけなら、{{...}}の形で書けばよいのではないか。