web-dev-qa-db-ja.com

AngularJSのモジュールと名前空間/名前の衝突

次のjfiddleを考慮してください http://jsfiddle.net/bchapman26/9uUBU/29/

//angular.js example for factory vs service
var app = angular.module('myApp', ['module1', 'module2']);

var service1module = angular.module('module1', []);

service1module.factory('myService', function() {
    return {
        sayHello: function(text) {
            return "Service1 says \"Hello " + text + "\"";
        },
        sayGoodbye: function(text) {
            return "Service1 says \"Goodbye " + text + "\"";
        }
    };
});

var service2module = angular.module('module2', []);

service2module.factory('myService', function() {
    return {
        sayHello: function(text) {
            return "Service2 says \"Hello " + text + "\"";
        },
        sayGoodbye: function(text) {
            return "Service2 says \"Goodbye " + text + "\"";
        }
    };
});

function HelloCtrl($scope, myService) {
    $scope.fromService1 = myService.sayHello("World");
}

function GoodbyeCtrl($scope, myService) {
    $scope.fromService2 = myService.sayGoodbye("World");
}​

2つのモジュール(module1とmodule2)があります。 module1とmodule2は両方ともmyServiceというサービスを定義します。これにより、Angularで両方のモジュールがmyAppにインポートされると、myServiceで名前の衝突が発生します。

非常に大規模なプロジェクト(または一般的なモジュールの再利用)では、名前が衝突するリスクがあり、デバッグが困難になる可能性があります。

名前の衝突が起こらないように、モジュール名を名前の前に付ける方法はありますか?

48
Brian Chapman

現在、AngularJSモジュールは、異なるモジュール内のオブジェクト間の衝突を防ぐような名前空間を提供していません。その理由は、AngularJSアプリには、モジュール名に関係なくすべてのオブジェクトの名前を保持する単一のインジェクターがあるためです。

AngularJS開発者ガイド 言う:

依存関係の作成の責任を管理するために、各Angularアプリケーションにはインジェクターがあります。インジェクターは、依存関係の構築と検索を担当するサービスロケーターです。

既に述べたように、メイン/アプリモジュールにモジュールを挿入すると、厄介なバグが発生する可能性があります。衝突が発生した場合、それらは沈黙し、勝者は最後に注入されたモジュールによって決定されます。

いいえ、これらの衝突を回避する方法は組み込まれていません。たぶん、これは将来起こるでしょう。この問題が発生する可能性が高い大規模なアプリの場合、命名規則が最良のツールであるというのは正しいことです。モジュールまたは機能領域に属するオブジェクトが短いプレフィックスを使用する可能性があるかどうかを検討してください。

62
Jim Ierley

常に一意になるように、命名規則を使用してモジュールに名前を付けることにより、この状況を回避できます。

1つのアプローチは、他の言語がどのように行うかを調べることです。たとえば、Javaのクラスの「フルネーム」は、ファイルの名前とそれが含まれるフォルダに基づいています。たとえば、Java = MyArtStuffフォルダー内のBitmap.Javaというファイル、クラスのフルネームはMyArtStuff.Bitmap

AngularJSでは、モジュール名の一部としてドット(。)を使用できるため、基本的に名前の規則を使用できます。

たとえば、開発者がスクリプト「MainPage\Module1.js」で「ModuleA」というモジュールを作成する場合、モジュールに「MainPage.Module1.ModuleA」という名前を付ける必要があります。各パスとファイル名はアプリ内で一意であるため、モジュール名は一意になります。

開発者にこの規約に従うようにすればよいだけです。

Rockalliteが指摘しているように、これは複数のモジュールに同じ名前を持つサービスやコントローラーなどには役立たないことに注意してください。ただし、同様のアプローチを使用して結果を取得し、それらの要素の名前にプレフィックスを付けることもできます。

理想的には、AngularJSには名前空間があり、将来的にはそうなる可能性があります。それまでは、名前空間が発明される前に開発者が40年以上にわたって行ってきたことを実行し、できる限り要素にプレフィックスを付けることができます。

2
Luis Perez

残念ながら、AngularJSにはnamespacingがありません。 1つの解決策はprefixを使用することです(別の解決策は this !かもしれません)。次の例を参照してください。

// root app
const rootApp = angular.module('root-app', ['app1', 'app2']);

// app 1
const app1 = angular.module('app1', []);
app1.controller('app1.main', function($scope) {
  $scope.msg = 'App1';
});

// app2
const app2 = angular.module('app2', []);
app1.controller('app2.main', function($scope) {
  $scope.msg = 'App2';
})
<!-- [email protected] -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular.min.js"></script>

<!-- root app -->
<div ng-app="root-app">

  <!-- app 1 -->
  <div ng-controller="app1.main">
    {{msg}}
  </div>

  <!-- app 2 -->
  <div ng-controller="app2.main">
    {{msg}}
  </div>

</div>
0
Yas