AngularJSをさわってみたよ

こんにちは~
エンジニアの井古田です。

 近年注目されているのJavaScriptフレームワーク、AngularJSを紹介します!
こっそり勉強してはいたものの、なかなか日の目を見る機会がありませんでした。
 しかし、社内ツール開発を機にこっそりAngularJSを投入し、今回エンジニアブログを書くまでにいたりました。

AngularJSの概要
  • AngularJSとは・・・
 AngularJSはGoogleとコミュニティにより開発しているオープンソース(MIT)のJavaScript用のMVWフレームワークです。
 テンプレート言語としてHTMLを使用し、双方向のデータバインディングやDI(依存注入)が容易にできます。

※MVWについて詳細を知りたい方はこちらから
MVWといっても基本的にはMVCの概念とあまり変わりません。
  • クライアントのテンプレートを書いてみた
 従来のアプリケーションでは、サーバ側でデータを元にHTMLを組み立て、完成下ページをブラウザに送るという手順をが取られていますが、AngularJSは、テンプレートとデータがブラウザに送られ、HTMLの組み立てをブラウザ側で行うという点が異なります。
 ここでのサーバの役割は、テンプレートを表す静的リソースを提供することと、テンプレートで必要となるデータを提供することです。
 
index.html
<html ng-app>
<head>
  <script src="controllers.js"></script>
</head>
<body>
  <div ng-controller='HelloController'>
    <input ng-model='greeting.text'>
    <p>{{greeting.text}}, World</p>
  </div>
</body>
</html>
スクリプトファイルのpathは適宣変更してください。

controller.js
function HelloController($scope) {
  $scope.greeting = { text: 'Hello' };
angularjs1


特徴
 ・イベントリスナーの関連付け先を指定するための、クラスやIDを記述するひつようがない
 ・HelloControllerがgreeting.textにHelloという文字列をセットする際に、イベントリスナーを設定したりコールバッグ関数を記述したりする必要がない
 ・HelloControllerはプレーンなJavaScriptのクラスであり、AngularJSのクラスを継承していない
 ・HelloControllerで必要とされる$scopeオブジェクトは自動的に渡される
 ・HelloControllerのコンストラクタを自分で呼び出す必要はなく、いつ呼び出すべきか考える必要もない
  •  簡単なMVCの説明
 MVCのコアとなる考え方は、データ管理(モデル)とデータの表示(ビュー)そしてアプリケーションロジック(コントローラー)を明確に分離すること。ビューはモデルからデータを取得し、ユーザーに提示、クリックやキーボートを通じてユーザーがアプリケーションを操作すると、コントローラはこれに応答してモデルのデータを変更する。そしてモデルはビューに対し、表示の更新を指示する。
 AngularJSアプリケーションでは、ビューはDOM(Document Object Model)として表現され、コントローラはJavaScriptのクラスであり、モデルのデータはオブジェクトのプロパティとして保持される。 
 AngularJSのWebアプリケーションのデータバインディングは、モデルとビューコンポーネント間のデータを自動的に同期します。ビューは常にモデル状態を投影し、モデルが変更されるとその変更がビューに反映され、その逆も然りです。
 ここで入力フィールドに表示されているHelloをHiに書き換えると、入力フィールドに対してイベントリスナーなどの設定は何も行っていなくても、動的に更新されるUIをを作成できまます。
  • 依存性の注入
 HelloControllerにはあまり多くの個度を記述していないのにも関わらず、その内部ではさまざまな処理が行われています。データバインディングのための$scopeは何もしなくても自動的に渡される。 コードに渡されるのは$scopeだけではなく$locationなども存在します。
 このような性質は、AngularJSでの依存性の注入(dependency injection)の仕組みによって実現されます。これを利用すると、依存先のオブジェクトを自身で生成せずに済み、必要な機能を列挙するだけ良くなります。これをLaw of Demeterというデザインパターンにしたがっています。
  • ディレクティブ
 AngularJSの優れた特徴に1つに、テンプレートをHTMLとして記述できるというものがあります。ここまでの例の中でも、HTML仕様に含まれていない属性が幾つか記述されています。データバインディングのための{{greetin.text}}、コントローラがビューのどの部分を監視するかの指定するためのng-controller、入力フィールドをモデルに結び付けるためのng-modelなどがあり、これらをディレクティブといいます.



ショッピングカートの例

  AngularJSをもう少し理解していただくために、簡単な例を紹介します。
作成するのは商品名と商品単価と個数と合計金額を表示するショッピングカートです。

index.html
<html ng-app>

<head>
  <title>ショッピングカート</title>
</head>

<body ng-controller='CartController'>
  <h1>注文内容</h1>
  <div ng-repeat='item in items'>
    <span>{{item.title}}</span>
    <input ng-model='item.quantity'>
    <span>{{item.price | currency}}</span>
    <span>{{item.price * item.quantity | currency}}</span>
    <button ng-click="remove($index)">削除</button>
  </div>
  <script>
    function CartController($scope) {
      $scope.items = [
      { title: 'ポテチ', quantity: 8, price: 3.95 }, 
      { title: 'コーラ', quantity: 17, price: 12.95 }, 
      { title: 'アイス', quantity: 5, price: 6.95 }
      ];

      $scope.remove = function(index) {
        $scope.items.splice(index, 1);
      };
    }
  </script>
</body>

</html>
angularjs2



上記のコードを手短に解説していきます。

<html ng-app>

ng-app属性は、ページ内でのAngularJSアプリケーションの範囲を指定するために使われます。ここでは先頭の<html>要素にng-appを宣言しているので、ページ全体がAngularJSによって管理されます。

<body ng-controller='CartController'>

AngularJSでは、ページ内の領域はコントローラと呼ばれるJavaScriptのクラスによって管理されます。

<div ng-repeat='item in items'>

ng-repeatは、配列itemsのそれぞれの要素ごとにこの<div>を繰り返しコピーするためのものです。
現在の要素がitemという名前のプロパティとして渡され、テンプレートの中で利用できます。この例では要素が
3つなので、<div>も3つ生成されます。

<span>{{item.title}}</span>

Hello, Worldの例も紹介しましたが、{{}}を使ってデータバインディングを行うと変数の値をページ内に埋め込むことができ、同期も保たれます。{{item.title}}と記述すれば、現在処理対象のitem属性がとりだされ、そのtitleプロパティの値がDOMに挿入されます。

<input ng-model='item.quantity'>

ng-modelは、入力フィールドとitem.quantityの値との間でデータバインディングを定義します。
ng-modelを宣言することで、item.quantityの現在の値が入力フィールドに挿入されるとともに、ユーザーが新しい値を入力したらitem.quantityも自動で更新されます。


<span>{{item.price | currency}}</span>
<span>{{item.price * item.quantity | currency}}</span>
    
今回単価と合計額の単位はドルで表記しています。AngularJSには文字列の変換を行うためのフィルタという昨日があり、currencyという組み込みのフィルタを使うと文字列を通過として表現できます。

<button ng-click="remove($index)">削除</button>

商品の隣に表示されている削除ボタンをクリックすると、カートから商品を削除することができます。これはng-clickを使用して、クリックのたびにremove()関数を呼び出します。ng-repeatの中での繰り返しのインデックスを表す$indexの値を渡すことによって、どの用品を削除するべきか伝えています。

function CartController($scope) {

ショッピングカートのロジックを受け持っているのがCartControllerです。ここで指定されている$scopeは、AngularJSから渡され、この$scopeによって、データがUI上の要求に関連付けられます。

$scope.items = [
{ title: 'ポテチ', quantity: 8, price: 3.95 }, 
{ title: 'コーラ', quantity: 17, price: 12.95 }, 
{ title: 'アイス', quantity: 5, price: 6.95 }
];

$scope.itemsには、カート内の商品を表すダミーのデータの配列が定義されています。
もちろん、実際のショッピングカートアプリケーションはブラウザ上だけでは実現できませんので、サーバとの
通信が必要となります。


$scope.remove = function(index) {
  $scope.items.splice(index, 1);
};

remove()関数についても、UI上で利用できるようにするために$scopeに追加しています。
この関数は単に配列の要素を削除しているだけです。ng-repeatが生成した<div>はデータと関連付けられているため、データが削除されるとリストの表示も短くなります。


以上で簡単なAngularJSの紹介を終わらせていただきます。
覚えることがたくさんあって、学習コストが大きいかもしれませんが、一旦サービスに入れるとすごく幸せなります。きっと。。。



最後に、AngularJSは公式サイトのチュートリアルが充実しているので、みなさんもぜひ試してみてください!