Browserify + BabelでAngularJs 1.xでES6を使用する

この記事では、ES6でAngularJsアプリケーションのコンポーネント部分を作成し、 githubからダウンロードして再生できる小さなアプリケーションに基づいて、BrowserifyとBabelを使用してアセンブルする方法について説明します。



コントローラーの作成



AngularJsのコントローラーは、$ scopeパラメーターをコントローラーコンストラクターに注入するか、コントローラーをアプローチとして使用することで作成されたスコープを拡張できるコンストラクター関数です。 最初に、例として登録コントローラーを使用して$スコープを注入するより一般的なアプローチを検討します。

class SignupController { constructor($scope, $state, accountService) { this.init($scope, $state, accountService); } init($scope, $state, accountService) { $scope.signup = function () { accountService.signup().then(()=> { $state.go('main.list'); }); }; } } SignupController.$inject = ['$scope', '$state', 'accountService']; export {SignupController}
      
      





ご覧のように、コントローラーはES6クラスで表され、$ scopeと2つのサービスの依存関係をコンストラクターに注入します。



ここで、インライン配列注釈を使用して依存関係を一覧表示する機能が失われたことにすぐに注意します。つまり、次のようになります。

 someModule.controller('MyController', ['$scope', 'greeter', function($scope, greeter) { // ... }]);
      
      





したがって、依存関係とその挿入順序を指定する機能は、作成されたSignupControllerクラスで定義されている$ injectプロパティを介してのみ残ります。



ES6クラスと組み合わせた場合、アプローチとしてコントローラーを使用してコントローラーを定義する2番目の方法は、より魔法のように見えます。 そして、コントローラーを書くとき、私はそれが最も好ましいと思います。



 var _state = new WeakMap(); var _accountService = new WeakMap(); class SigninController { constructor($state, accountService) { _state.set(this, $state); _accountService.set(this, accountService); } login() { _accountService.get(this).login().then(()=> { _state.get(this).go('main.list'); }); }; } SigninController.$inject = ['$state', 'accountService']; export {SigninController}
      
      





ご覧のとおり、クラスはスコープの明示的な言及を失い、AngularJsからもう少し独立し、さらにコンストラクターを通じて依存関係が注入されています。 しかし今では、プライベート変数がクラスに表示され、クラス内での使用の問題が発生します。 これについては記事「 JavaScriptでWeakMapを使用してPrivate Fieldsを実装する 」で非常に簡単に書かれており、リソースの解放とこのクラスのみへの変数の所属を保証する最良のソリューションは、WeakMapを使用することです。



最後のステップは、AngularモジュールでControllerを宣言することです。



これを行うために、別のmodule.jsファイルを作成しました。このファイルには、ES6モジュールがインポートされ、Angularモジュールに登録されています。



 import router from './router.js'; import {SigninController} from './controllers/signin/signin.controller.js'; angular.module('account').controller('SigninController', SigninController);
      
      





ライティングプロバイダー、工場、サービス



次のステップは、ビジネスロジックのクラスを実装することです。私の場合は、AccountServiceクラスになります。



前のクラスと同じように魔法のように見えます-AngularJsの言及なし



 import api from './accountApi.factory.js'; class AccountService { login(){ return api.login(); } signup(){ return api.signup(); } } export {AccountService}
      
      





AccountServiceクラスはaccountApi.factory.jsファイルで宣言されたモジュールに依存しますが、AngularJsが提供するDIメカニズムを使用して注入されるのではなく、依存関係がインポートされることに注意してください。 原則として、AccountServiceコントローラーは、上記のコントローラーに挿入するのではなくインポートできます。 それはすべて、アプリケーションの構築方法によって異なります。



そのため、サービスクラスについて説明しましたが、Angularモジュールでサービスを宣言する必要があります。



Angularサービスは最も簡単に宣言できます。 FactoryとProviderでは、事態はもう少し複雑です。



module.jsファイルでサービスを宣言します。



 ........ import {AccountService} from './services/accountService.factory.js'; ......... angular.module('account').service('accountService', AccountService);
      
      





ここではすべてが単純です。サービスメソッドはコンストラクター関数を想定しているため、newServiceを使用してAccountServiceクラスのインスタンスが作成されます。



プロバイダーを宣言する必要がある場合、コードは次のようになります。



 angular.module('account').provider('accountService', providerBuilder(AccountService)); function providerBuilder(obj) { return function () { this.$get = [function () { return new obj(); }]; } }
      
      





最後に、工場が必要な場合:



 angular.module('account').factory('accountService', function(){return new AccountService()});
      
      





また、クラスのインスタンスを作成するAccountServiceクラスで静的関数を宣言すると、コードは次のようになります。



 angular.module('account').factory('accountService', AccountService.createInstance);
      
      





同様の動作の例を以下に示します。



ライティングディレクティブ



ディレクティブは次のようになります。

 var _accountService = new WeakMap(); class Copyright { constructor($templateCache, accountService) { _accountService.set(this, accountService); this.restrict = 'E'; this.template = $templateCache.get('account/directives/copyright/copyright.directive.html'); this.scope = {}; this.controller = ['$scope', function ($scope) { $scope.copyright = function () { return 'Page - 2015'; }; }]; } link(scope) { scope.doSomething = function () { //-  var accountService= _accountService.get(Copyright.instance); //-  } } static createInstance($templateCache, accountService) { Copyright.instance = new Copyright($templateCache, accountService); return Copyright.instance; } } Copyright.createInstance.$inject = ['$templateCache', 'accountService']; export {Copyright}
      
      





私のディレクティブは何もしませんが、すべての主要部分を持っています。



クラスでは、必要なすべての標準ディレクティブフィールドを定義し、ディレクティブの宣言方法に注意を向けたいと思います。

ディレクティブはAngularモジュールでファクトリとほぼ同じ方法で宣言されていますが、1つの小さな違いがあります:コンストラクター関数のこれはリンク関数のこれと等しくないため、クラスのインスタンスフィールドにこれへのリンクを保存します。



同様に、フィルター、定数、および値を宣言できます。



プロジェクトの組み立て



そのため、ES6モジュールに分割されたコードをいくつか作成しましたが、今はそれをまとめる必要があります。 Browserifyは、モジュールの依存関係を見つけ、それらを単一のファイルにアセンブルする役割を果たします。 これを行うには、まず、アセンブリを開始するエントリポイントを決定します。



2つのエントリポイント(モジュールのエントリポイント)を定義することをお勧めします。つまり、そのモジュールのみのモジュール/ファイルをインポートするファイルと、モジュールのエントリポイントを結合する共通のエントリポイントです。



ただし、モジュールは1つしかないため、このようなファイルは2つしかありません。

  1. アカウントフォルダーのルートにあり、使用されているすべてのモジュールファイルへの相対リンクを持つmodule.jsファイル
  2. アプリケーションのルートにあり、すべてのプロジェクトmodule.jsファイルへのリンクを持つapp.jsファイル


2番目のタスクは、ES6で記述されたコードをES5に変換することです。 このタスクはBabelによって実行され、変換オプションを使用してプラグインとしてBrowserifyに接続されます。



コレクターのコードとプロジェクトのコードはgithubリポジトリで見つけることができます



参照:

  1. AngularJSドキュメントのガイド
  2. JavaScriptでWeakMapを使用してプライベートフィールドを実装する
  3. watchifyを使用した高速browserifyビルド



All Articles