AngularJSアプリケーションを分離されたモジュールに分離する

十分に大きなアプリケーションを開発するとき、アプリケーションが最終的に減速するのに十分な大きさになる瞬間が必然的に生じます。 AngularJSが目的のパフォーマンスを達成するための多くの方法があります: bindonce 、リストのフィルタリング、$ applyの代わりに$ digestの使用、ng-showの代わりのng-if(またはその逆) など 。 しかし、これらはすべて、グローバルに支援することなく、ローカルの改善のみを行うことができます:$ rootScope呼び出しを完全に削除します$ダイジェストは失敗し、アプリケーション全体のステータスのチェックには非常に長い時間がかかります。



この記事では、アプリケーションをフレームワークの観点で関係のないいくつかの部分に分割し、それらの間の関係を独立して実装するアーキテクチャソリューションを提供します。



Angularには、 ブートストラップの概念があります。 これは通常、ng-app属性を持つ要素がある場合にページが読み込まれた後に呼び出されるメソッドです。 この要素を、属性値で指定されたモジュールにバインドします。 そのような要素は1つだけである必要があります。そうでない場合、ドキュメントは何も保証しません。 ただし、手動で使用できますangular.bootstrap(element, [/*Module*/]);



これにより、指定したモジュール、そのすべての依存関係、およびngモジュールとその依存関係が起動します。 したがって、新しいアプリケーション(独立したモジュールと呼びましょう)には、独自の$インジェクター、$ rootScope、$ compileなどがあります。 -内部Angularキッチン全体が再作成されます。 親の隔離されたモジュールはネストされたモジュールの存在を知らず、イベント(送信とブロードキャスト)はモジュール間を通過せず、隔離されたモジュールで呼び出された$ダイジェストは別のモジュールにリークしません。 疎結合コンポーネントの場合、これが必要です。



新しいアプリケーションを簡単に作成するには、次のディレクティブを使用できます。
 directive('newApp', function () { return{ restrict: 'EA', transclude: true, scope: { module: '=' }, link: function (scope, element, attr, ctrl, transclude) { var div = document.createElement('app'); var module = angular.module(scope.$id, [scope.module]).run(['$rootScope', function ($rootScope) { scope.$on('$destroy', function() { $rootScope.$destroy(); angular.module(scope.$id, []); }); transclude($rootScope, function (el) { angular.element(div).append(el); element.append(div); }); }]); angular.bootstrap(div, [scope.$id]); } }; });
      
      





使用法:
 <body ng-app="App"> <new-app module=" 'SomeModule' "> <some-module-directive/> </new-app> </body>
      
      







前後のパフォーマンスを比較するために、合成の例を見ることができます: 低速バージョン高速バージョン



メモリリークについても言及する必要があります。 存在しない場合、ディレクティブの$ destroyイベントハンドラーが責任を負います。 彼はこのイベントを隔離されたモジュール内に送信して、誰もがそれを認識し、登録されたディレクティブやコントローラーなどを削除するようにモジュールを書き換えます。ただし、たとえば、angular.element.cacheの要素のキャッシュなどにより、メモリは依然としてリークします。 この問題は、別の研究と記事に値します。



発見された別の問題は、$位置情報サービスです。 とりわけ、彼はページのアドレスを監視し、それを変更するとき、たとえばngViewのコンテンツを更新するなど、何らかのジェスチャーを行います。 複数の分離されたモジュールの場合、$ locationのインスタンスがいくつか作成され、URLを変更するためのハンドラーがいくつか作成されますが、これは良くありません。 これまでのところ、次の回避策を思いつきました。
 .config(function ($locationProvider) { $locationProvider.$get = function () { return angular.element(document).injector().get('$location'); }; })
      
      





今、私はライブラリの形でコードをテストおよび設計していますが、コミュニティの意見に興味があります。



All Articles