AngularJSをRequireJSで利用する
続いて、RequireJSを用いて前回作成したSPAのサンプルをRequireJSに対応させていきます。ただし、今回のサンプルではAngularJSやその関連プラグインはRequireJSでの依存として取り扱いません。したがって、それらのファイルはリスト3のようにHTMLファイル内に静的にscriptタグで記述しています。これでRequireJSでのモジュールの定義(define関数の利用)でAngularJSの依存の記述をしなくて済むので記述が簡単になります。このように、すべての依存を管理する必要はありません。まずは、RequireJSに慣れていき自分なりの管理方法を探してみて下さい。
<script type="text/javascript" src="vendors/angular.js"></script> <script type="text/javascript" src="vendors/angular-route.js"></script> <script type="text/javascript" data-main="js/all.js" src="vendors/require.js"></script>
今回のサンプルは図2のようなファイル構造となっています。赤字がAngularJSのモジュール名となり、ファイルとの関係性がわかるようになっています。
data-main属性で指定したファイルがリスト4です。
require([ 'app', ],function(){ angular.bootstrap(document,['app']); });
また、依存するapp.jsはリスト5のようにAngualrJSでのモジュールを定義しています。
define(['controllers','services','routes','directives'],function(){ angular.module('app',['app.controllers','app.services','app.directives','app.routes']); });
そして、コントローラ群を管理するモジュールとして"app.controllers"は、リスト6のようになります。同様に、ディレクティブやサービスなども別のモジュールとして定義しています。詳しくはサンプルコードを参照して下さい。
define([ 'controllers/AppController', 'controllers/ListController', 'controllers/AddController', 'controllers/ItemController' ], function(AppController,ListController,AddController,ItemController){ var module = angular.module('app.controllers',[]); module.controller('AppController',AppController); // (1) DIの指定が記述されていない module.controller('ListController',ListController); module.controller('AddController',AddController); module.controller('ItemController',ItemController); });
AngularJSのモジュールを利用する場合にはこのように、各define関数内で戻り値を使用する必要がなくすっきりとした記述ができます。ただし、(1)のようにこれまで各コントローラの記述の際には、併せてDIの指定がありましたがその記述をなくしています。これは、各コントローラの独立性を高めるためで、コントローラ側のAngularJSの依存性は個別のコントローラ側のファイルで管理するようにします。
AngularJSのDI記述方法
各コントローラ側を定義するファイルは、これまでリスト7のようにモジュールへの追加時に無名関数として定義していました。
(function(module){ module.controller('AppController',['$scope',function($scope){ $scope.$on('title',function($evt,$title){ $scope.title = $title; }); }]); }(app.module));
しかし、モジュールへの追加はその上位であるjs/controllers.jsによって行っていますが、そちらではDIの指定は行いません。
したがって、リスト8のようにコントローラの実装部分とDI指定を行います。
define([],function(){ // (1) RequireJSのモジュール定義 function AppController($scope){ $scope.$on('title',function($evt,$title){ $scope.title = $title; }); }; AppController.$inject = ['$scope']; // (2) AngularJSでのDIの指定 return AppController; });
このとき、(1)では、これ以上のRequireJSでの依存ファイルはないので第一引数では空配列となります。また、今までcontrollerメソッドで行っていたDI指定は(2)のように$injectプロパティを使って指定します。この$injectプロパティを用いたDIの記述方法はコントローラ以外にもディレクティブ、サービスなど他でも利用できます。
AngularJSでは様々な記述方法がありますので、このようなファイルの構造を変化にも耐える事ができます。