AngularJS中的模块和命名空间/名称冲突

时间:2012-11-15 21:46:19

标签: angularjs namespaces collision angularjs-module

考虑以下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的服务。当两个模块都导入myApp时,这似乎会在Angular中的myService上创建名称冲突。看来AngularJs只使用第二个服务定义而没有警告您可能出现的问题。

非常大的项目(或者只是重复使用模块)会有名称冲突的风险,这可能很难调试。

有没有办法为名称添加模块名称,以便不会发生名称冲突?

4 个答案:

答案 0 :(得分:62)

截至今天,AngularJS模块不提供任何类型的命名空间,以防止不同模块中的对象之间发生冲突。原因是AngularJS应用程序有一个注入器,它保存所有对象的名称而不考虑模块名称。

AngularJS Developer Guide说:

  

管理依赖关系创建的责任,每个Angular   应用程序有一个注射器注入器是一个服务定位器   负责构建和查找依赖项。

正如您所提到的,将模块注入主/ app模块时可能会产生令人讨厌的错误。碰撞发生时,它们是静音的,胜者是由最后一个模块注入的。

所以不,没有内置的方法来避免这些碰撞。也许这将在未来发生。对于更有可能出现此问题的大型应用程序,您认为命名约定是最佳工具是正确的。考虑属于模块或功能区域的对象是否可能使用短前缀。

答案 1 :(得分:2)

您可以通过使用约定命名模块来避免这种情况,以便它们始终是唯一的。

一种方法是看其他语言是如何做到的。例如,在Java中,类的“全名”基于文件的名称及其所在的文件夹。例如,如果在MyArtStuff文件夹中有一个名为Bitmap.java的Java文件,则该类的全名将为是MyArtStuff.Bitmap

结果证明,AngularJS允许您将点(。)作为模块名称的一部分,因此您基本上可以使用名称约定。

例如,如果开发人员在脚本“MainPage \ Module1.js”中创建名为“ModuleA”的模块,则应将其模块命名为“MainPage.Module1.ModuleA”。由于每个路径和文件名在您的应用中都是唯一的,因此您的模块名称将是唯一的。

您只需要让开发人员遵循此惯例。

请注意,Rockallite指出这对多个模块中具有相同名称的服务,控制器等没有帮助。但是你可以使用类似的方法得到结果,并为这些元素的名称添加前缀。

理想情况下,AngularJS会有名称空间,将来也可能。在此之前,我们所能做的最好的事情就是在开发名称空间之前40多年来开发人员已做的事情,并尽可能地为我们的元素添加前缀。

答案 2 :(得分:0)

不幸的是, AngularJS 中没有namespacing。一种解决方案是使用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';
})

<!-- angularjs@1.7.0 -->
<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>
&#13;
&#13;
&#13;

答案 3 :(得分:-8)

在您希望服务来自的模块上定义控制器。

service2Module.controller("ServiceTwoCtrl", function(myService, $scope) {});