[AugularJS]moduleAPIに関してまとめ(夏休み企画2)

前回の記事の続き

前回はdirectiveの定義のためだけに、とりあえずmoduleを作成しましたが、 今回はmoduleを定義することで出来ること、つまりmoduleAPIに関して 調べてまとめて、可能ならサンプルを用意して再現してみたいと思います。

公式リファレンスで紹介されているAPI群

公式リファレンスを見たところ、そこまで量が多いわけでもなさそうなので moduleAPIで提供している全てのメソッドをザックリと訳していきます。

●config(configFn) *

Use this method to register work which needs to be performed on module loading. Execute this function on module load. Useful for service configuration.

モジュールがロードされたときに実行される処理を記述します。 通常、serviceの設定をするときに利用します。

●constant(name, object)

Because the constant are fixed, they get applied before other provide methods. See $provide.constant().

ここ、よくわからないんですが、多分 他の関数が提供される前に、objectが宣言できる、とかそんな感じ、だと思う。 他の関数で共通で利用したいobjectとかをここで宣言したらいい、のかな・・・。

●controller(name, constructor) *

コントローラーの定義を行います。

  • 第一引数:コントローラー名
  • 第二引数:コントローラーの生成の関数

●directive(name, directiveFactory) *

独自directiveの定義

  • 第一引数:directive名
  • 第二引数:directiveのインスタンス生成の関数

●factory(name, providerFunction)

独自のserviceの定義

  • 第一引数:service名
  • 第二引数:servideで提供する処理

※serviceと違い、インスタンスではなく結果が返される

●filter(name, filterFactory)

独自filterの定義

  • 第一引数:filter名
  • 第二引数:filterのインスタンス生成の関数

●provider(name, providerType)

独自のserviceの定義

  • 第一引数:service名
  • 第二引数:servideで提供する処理

※serviceと違い、インスタンスではなく$get()メソッドの結果が返される

●run(initializationFn)

Use this method to register work which should be performed when the injector is done loading all modules. Execute this function after injector creation. Useful for application initialization.

全てのmoduleのロードが終わった後に、実行する処理を記述します。configと違い、通常アプリケーションの 初期化に、runメソッドを利用する。

●service(name, constructor)

独自のserviceの定義

  • 第一引数:service名
  • 第二引数:servideのインスタンス生成の処理

※factoryと違い第二引数で作られたインスタンスそのものが返されることに注意

●value(name, object)

アプリケーション内の定数を定義するときなどに利用


※比較的よく見かけるものには*をつけています。


factory, service, providerの違い

3つとも独自のserviceを提供するものです。それではこの3つは、それぞれ何が違うのでしょう。

結論から言うと、すいません、僕も言葉でハッキリ説明することはできません・・・。

ですが、同様の疑問は多く寄せられていて、議論されているようです。

  1. Angular.js: service vs provide vs factory?
  2. Difference between Service, Factory and Provider in AngularJS
  3. 同じ関数をそれぞれ3つのAPI渡したときの違い

これらを見れば、おおまかに違いがわかると思います。

  1. serviceはインスタンスを返す(第二引数内のconstructorでreturnしても無意味)
  2. factoryはデータを返す(第二引数のproviderFunction内のreturnが全て取得できる)
  3. providerは$get()メソッドの結果を返す($get()メソッドのreturnのみ取得でき、moduleAPIのconfigで 更に設定・アクセスすることができる)

前回の記事で、moduleを定義を

  1. serviceの定義
  2. directiveの定義
  3. filterの定義
  4. アプリケーションの設定と1-3をインポートするmoduleの定義

を推奨している、と書きましたが、汎用的なproviderを1で定義して 細かい設定をmodule.configを使って4で追加すると、良い感じに処理とデータを 分離できるかもしれません。(見当違いなこと言ってる気もします。)

こんな感じ・・・?もうちょっとソースコード収集して、比較すれば更に詳しく理解できるかも・・・。 意味不明、という状況ではなくなったので、とりあえずここまで。


実際に使ってみる

●まずは公式が推奨している形でそれぞれを定義してみる

filter, directive, serviceにファイルを分けて、それぞれで、対応するAPIを 利用してみました。

サンプル2

こんな感じで、他で定義したmoduleをインポートしています。

●filter使ってみた

サンプル2(filter.js)

公式のチュートリアルにもあった、文字を受け取って、Hello ‘text’ !の形式にして 返すfilterです。

もうひとつは、userというオブジェクトを受け取って、IDと名前を連結して 返すだけのfilter。簡単ですね。

データベースや、jsonから取得したデータがフラグ(true/falseとか1/0)だったときに このfilterを使って出力を変えてあげたりすれば便利ですね。 (male/famaleを男性/女性に変えたり誕生日のフォーマットを変換したり、などなど)

●directive使ってみた

サンプル2(directive.js)

HEADER

FOOTER

これは前回の記事と同じ。 公式の書き方を真似して、今回はtemplateUrlではなくtemplateに文字列連結で書いてみました。

やってることは全く同じ。それに加えて、公式チュートリアルにあるmy-current-timeのdirectiveを ちょいと改造したものを追加してみました。任意のタグにmy-current-timeをつけるだけで 現在時刻をリアルタイム表示してくれるattributeです。

directive()の中のreturnで、restrictなどを指定しなければデフォルトでは’A’になり、template もナシです。

宣言したdirectiveの名前を含んだDOMエレメントに対して、return内の関数が実行される、っていう感じかな・・・?(なんかうまく説明できないし、そもそも理解できてるか不安・・・)

updateTime()関数はdirectiveの名前が指定されたDOMエレメント内を、dataFilterで整形して テキストを更新する関数

updateLaterは$timeoutというserviceを利用して1000ミリ秒ごとにupdateTime()とupdateLater()を 呼び出しています。

まずmy-current-timeというattributeがついたDOMエレメントがあると、updateLater()を呼び出して、 その中で更にupdateLater()を再帰呼び出しが行われることで、 リアルタイムに時刻がカウントされています。

●serviceを使ってみた(factory, service, provider, config)

サンプル2 service.js

僕の中で、MVCモデルにおけるserviceのポジションが、controllerをサポートする、みたいな感覚なんですが、 まずそれ合ってますかね・・・。

開発の過程でcontrollerに複数のモデルのインポートが必要になったときや、 複雑な処理が複数必要になったときに それらをまとめて代わりに引き受けて、わかりやすいインターフェースを提供する、みたいな。

その認識が合ってるか、どうかはまぁ置いといて、とりあえず使ってみました。

先ほど挙げた参考リンクと同じように、factory,service,providerをそれぞれ、同じ用途で 書いてみました。書き方や使い方に違いがあることを確認できると思います。

ID以外はデータの中身そのまんまですが、コメントアウトとかして、利用するserviceを 切り替えると、取得できるデータが違うことが確認できます。

●controllerを使ってみた

サンプル2 app.js

これはもう今さらですね・・・。前回の記事でも書きました。

ずっと使ってるサンプル内のコントローラー。

RailsやPlay,strutsでいうアクションみたいなものを書きたければ

のように書けばOKです。 (※アクションっていうよりイベントっていうのかな・・?)

これでボタンクリックしたらevent()が動作します。

ちなみに公式チュートリアルや多くのサンプルではコントローラーをグローバル関数として 定義していますが、あくまでサンプル用に簡易に定義するためのものです。

本来はmodule.controller()でコントローラー定義することが推奨されています。

●run, valueを使ってみた

サンプル2 app.js

これ、全然いいサンプルじゃないんですが、とりあえずrun()を使う & 次回以降のどこかで ちゃんと調べたいと思ってる$location serviceをとりあえず使う、サンプルにしました。

アプリが起動(サンプル内のmyApp moduleが読み込まれると)すると、現在のページのhostを alert()で出力するだけです。

アプリケーション起動時の設定や処理をここに記述します。

サーバサイドのフレームワークでいうbootstrapみたいなものだと思います。

valueを使うのは簡単です。簡単ですが、これ、わざわざ使うことがあるのかな・・・って ちょっと思ってるんですけど、明確に定数を定義したいとき、なんかに使うのかなぁ・・・。

全部を1つのコントローラーで無理矢理使おうと、サンプルを書いてるから、なのかもしれませんが いろんなmodule, serviceなどなどが、コントローラーの引数にどんどん増えていくんですよねぇ・・・。


constant以外はこれで、とりあえず使ってみた形になります。ざっくりとした用途・使い方は確認できました。

なんか調べれば調べるほど、『これも知らないと理解できないな』っていうことが増えてきてますが、 まぁ前進はしてます。夏休み中にまとまった知識がつけばいいけど・・・。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です