7

フィルター、サービス、ルートなどの 200 を超える場所に $rootscope がアプリ全体に散らばっている大規模な Angularjs 1.6 アプリケーションがあります。アプリケーションで $rootscope を使用するベスト プラクティスはいつですか?

コントローラー間でデータを共有するためであると想定した変数の保存に使用することまで、決して読んだことはありません。それ以来、このユース ケースでは代わりにファクトリ/サービスを使用する方がよいことを読みました。有効なユース ケースの 1 つは $rootscope をグローバル イベント バスとして使用することでもあると読みました。

これがAngularjsのドキュメントで説明されているのを実際には見ませんでした。

4

3 に答える 3

10

ng-bookから:

Angular が実行を開始してビューを生成すると、ルート ng-app 要素から $rootScope へのバインディングが作成されます。この $rootScope は、すべての $scope オブジェクトの最終的な親です。$rootScope オブジェクトは、Angular アプリのグローバル コンテキストに最も近いオブジェクトです。このグローバル コンテキストにあまりにも多くのロジックを追加するのは、JavaScript のグローバル スコープを汚すのと同じように、悪い考えです。

その通りです。モジュール間でデータとロジックを共有するには、必ずサービスを使用する必要があります。

$rootScopeに多くのロジックを配置すると、アプリケーションの保守性とモジュール性が低下し、問題をテストすることも非常に困難になります。

以下をご覧になることを強くお勧めします。

すべてを$rootScopeにアタッチするのは簡単かもしれませんが、それに取り組み、少し変更を加え、コードを他のアプリケーションやモジュールに再利用し、アプリケーションを一般的にテストするのは難しいです。

編集

最近、特定のビューに表示するために、API からいくつかのアイテムを取得し、これらのアイテムをキャッチする必要がありました。アイテムを取得するメカニズムは特定のFactoryにありましたが、アイテムをフォーマットして表示するメカニズムは にありましたController

そのため、Factoryアイテムがフェッチされたときにイベントを発行し、このイベントを でキャッチする必要がありましたController

$rootScope の方法

//Factory
$rootScope.$broadcast('refreshItems', items);
//Controller
$scope.$on('refreshItems', doSomething());

それは明らかに機能しましたが、私はあまり使いたくありませんでした$rootScope。また、そのタスクのパフォーマンスがかなり悲惨であることに気付きました.

次に、Postal.jsを試してみました。

Postal.js は、JavaScript で記述されたメモリ内メッセージ バスです。Postal.js はブラウザで実行されるか、node.js を使用してサーバーで実行されます。これは、おなじみの「イベント スタイル」パラダイム (ほとんどの JavaScript 開発者がよく知っている) を採用し、単純なイベントの発行/集約で通常見られるものよりも洗練された「ブローカー」およびサブスクライバーの実装を提供することによってそれを拡張します。

この種のニーズに使用してみましたが、この目的Postal.jsで使用するよりも本当に高速であることがわかりました。$rootScope

//Factory
$scope.$bus.publish({
                  channel : 'reloadItems',
                  topic   : 'reloadItems'
                  data    : items
);

//Controller
$scope.$bus.subscribe({
  channel  : 'reloadItems',
  topic    : 'reloadItems',
  callback : function () {
    resetAndLoadItems();
  }
});

お役に立てば幸いです。

于 2016-02-11T17:27:45.480 に答える
3

Angluar ドキュメントから: すべてのアプリケーションには単一のルート スコープがあります。他のすべてのスコープは、ルート スコープの子孫スコープです。スコープは、モデルの変更を監視するメカニズムを介して、モデルとビューを分離します。

もちろん、これは意見とスタイルの問題になります。私はJohn Papa の Angular Style Guideに非常に近いスタイルに従う傾向があります。

この 2 つを維持し、適切な関心の分離戦略に従って、私のアーキテクチャには、アプリケーション全体で共有されるファクトリ モデルが含まれています。私のコントローラーはすべて、共有データを保持するサービスにバインドされています。

$rootScope をグローバル イベント バスとして使用することは、まさに Angular がそれを使用する方法です。タグを付けて同じことをする必要がありますか? 理由がわかりません。ただし、その場合は、目的が明確に定義されていることを確認し、独自のサービスを使用してイベントをグローバル イベント バスに登録することもできます。そうすれば、アプリを Angular から切り離すことができます。グローバル イベント バスが存在するフレームワークを変更したい場合は、1 か所で変更できます。

これは私が提案しているものです:

グローバルイベントバス

// Angular specific: add service to module
angular.module('app').factory('globalEventBus', GlobalEventBus);

// Angular specific: inject dependencies
GlobalEventBus.$inject(['$rootScope']);

// Non framework specific. 
// param: fameworkEventBus will be $rootScope once injected 
function GlobalEventBus(fameworkEventBus) {

  var globalEventBus = this;

  globalEventBus.registerEvent(params...){
    fameworkEventBus.
  }

  return globalEventBus;
}

グローバル データ モデル

私のデータモデルはスマートで、それ自体に関する情報を提供したり、特定のデータを取得/返す関数を含む傾向があります。

// Angular specific: add service to module
angular.module('app').factory('dataModel', DataModel);

function DataModel() {

  var dataModel= this;

  dataModel.myData = {};

  dataModel.GetSpecificData = funtion(param){
    return ...
  }

  return dataModel;
}

コントローラー

// Angular specific
angular.module('app').controller('MyController', MyController);

// Angular specific: inject dependencies to controller
MyController.$inject = ['dataModel'];

// By convention I use the same parameter name as the service.
// It helps me see quickly if my order of injection is correct
function MyController(dataModel) {

  var myController = this;

  // Bind to the service itself, and NOT to the service data property
  myController.myData = dataModel;

  myController.doStuff = function(){
  }
}

これは、サービス プロパティではなく、サービスへのバインドに関する楽しい投稿です。

全体として、自分にとって何が最適かを判断するのは自分自身である必要があります。優れたシステム アーキテクチャと優れたスタイルのおかげで、完全に回避可能な問題を解決するために数え切れないほどの時間を節約できました。

于 2016-02-11T17:48:47.070 に答える
1

Angularでさらに作業を行い、さらに読んだ後、 $rootscope を使用するためのこの基本的な経験則を見つけ、他の回答に追加したいと考えました。

静的または定数のプロパティのみを追加します。変化する状態または変更可能な値を表すその他のものには、それを処理するための対応するディレクティブまたはコントローラーが必要です。

于 2016-03-31T20:45:08.270 に答える