AngularJS种子:将JavaScript放入单独的文件(app.js,controllers.js,directives.js,filters.js,services.js)


93

我正在使用角度种子模板来构建我的应用程序。最初,我将所有JavaScript代码放入一个文件中main.js。该文件包含我的模块声明,控制器,指令,过滤器和服务。该应用程序可以像这样正常运行,但是随着我的应用程序变得越来越复杂,我担心可伸缩性和可维护性。我注意到,每个角度种子模板都有单独的文件,因此我尝试将我的代码从单个main.js文件分发到该问题标题中提到的每个其他文件中,并且可以在app/js每个角度的目录中找到种子模板。

我的问题是:如何管理依赖关系以使应用程序正常工作?在这方面,此处找到的现有文档不是很清楚,因为给出的每个示例都显示一个JavaScript源文件。

我所拥有的一个例子是:

app.js

angular.module('myApp', 
    ['myApp.filters',
     'myApp.services',
     'myApp.controllers']);

controllers.js

angular.module('myApp.controllers', []).
    controller('AppCtrl', [function ($scope, $http, $filter, MyService) {

        $scope.myService = MyService; // found in services.js

        // other functions...
    }
]);

filter.js

angular.module('myApp.filters', []).
    filter('myFilter', [function (MyService) {
        return function(value) {
            if (MyService.data) { // test to ensure service is loaded
                for (var i = 0; i < MyService.data.length; i++) {
                    // code to return appropriate value from MyService
                }
            }
        }
    }]
);

services.js

angular.module('myApp.services', []).
    factory('MyService', function($http) {
        var MyService = {};
        $http.get('resources/data.json').success(function(response) {
            MyService.data = response;
        });
        return MyService;
    }
);

main.js

/* This is the single file I want to separate into the others */
var myApp = angular.module('myApp'), []);

myApp.factory('MyService', function($http) {
    // same code as in services.js
}

myApp.filter('myFilter', function(MyService) {
    // same code as in filters.js
}

function AppCtrl ($scope, $http, $filter, MyService) {
    // same code as in app.js
}

如何管理依赖关系?

提前致谢。


2
有一些关于此的文章。例如briantford.com/blog/huuuuuge-angular-apps.html和一些项目,例如yeoman。有两种方法可以解决此问题:按层(如角种子)或按特征分开组件,如某些文章所建议的。
爱德华·加莫纳尔

当您声明一个模块时,例如angular.module('myApp.service1',[]),我认为您需要向[]添加依赖项,例如angular.module('myApp.service1',['myApp.service2','myApp .service2'])。。我是AngularJS的新手,所以我可能是错的。如果可以解决,请通知我,我会发布答案。
Danny Varod 2013年

该行应插入哪里?我angular.module('myApp.services', ['myApp.services']);没有运气就进入了app.js。
ChrisDevo 2013年

@ChrisDevo 1.回复评论时,始终以“ @”和用户名(不带空格)开始评论,以便用户收到通知。2. myApp.services应该依赖于其他模块,而不是自身,例如angular.module('myApp.services', ['myApp.server', 'myApp.somethingElse'])
丹尼·瓦罗德

@DannyVarod,您是否编辑了以前的评论?我按angular.module('myApp.service1', ['myApp.service1', 'myApp.service2'])原样阅读。否则,我不会将myApp.services作为其自身的依赖项包含在内。
克里斯德沃(ChrisDevo)

Answers:


108

该问题是由您在所有单独文件中“重新声明”您的应用程序模块引起的。

这是应用程序模块声明(不确定声明是否正确)的样子:

angular.module('myApp', []).controller( //...

这就是对应用程序模块的分配(不确定分配是否也是正确的术语),如下所示:

angular.module('myApp').controller( //...

请注意缺少方括号。

因此,以前的版本(带有方括号的版本)仅应使用一次,通常在app.js或中使用一次main.js。所有其他关联文件(控制器,指令,过滤器 ……)应使用后一种版本,即不带方括号的版本。

我希望这是有道理的。干杯!


9
我已经找到解决此问题的方法。似乎只需要一个模块myApp。在我的app.js文件中,我为此创建了一个变量。var myApp = angular.module('myApp', []);在所有其他文件中,我都简单地引用了该myApp.filter('myFilter', function(MyService) { /* filter code */ });变量(例如,只要我在html的脚本标签中添加文件名,就不需要声明其他变量了)。角度种子项目模板在这方面非常令人困惑
ChrisDevo 2013年

1
现在我真的很困惑。我回去并删除了全局变量myApp,因此它现在是app.js:中的匿名模块angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers']);。在所有其他文件中,我还声明了这样的匿名模块angular.module('myApp.filter', []).filter('myFilter', function(MyService) { /* filter code */ });。我的应用程序现在也可以像这样工作。我已经查看了我的代码历史记录,并且看不出它与无法正常工作的地方有什么不同。
克里斯德沃(ChrisDevo)

4
我向你保证这行得通。我每天都在开发Angular Apps时使用它。同样,angular.module('myApp', []);我的主js文件中有一个声明(请注意方括号)。然后,所有其他文件使用angular.module('myApp').controller.directive语法引用该模块。
贾斯汀·

5
导致这些错误的原因是Angular正在寻找名为myApp.controller,myApp.filters的模块……但是,这些不是模块,它们是扩展名为myApp的一个模块的组件。如果从模块依赖项中删除所有myApp.what,一切都会正常。在声明您的主要应用程序模块时,只需保持方括号为空(除非您包括其他真正的角度模块,例如ngCookiesngResource),即可:angular.module('myApp', []);
Justin L.

1
啊好吧。通过将它们放置为您的应用程序模块的依赖项,它将出错,因为它必须找到它们。如果您将它们从方括号中取出,则可以随意加载它们,而您的应用程序将不在乎。ngResource绝对是您放在模块声明括号中的那些文件之一。如果我的回答对您有所帮助,请投票并批准它。
贾斯汀·

12

如果您想将应用程序(filters, services, controllers)的不同部分放在不同的物理文件中,则需要做两件事:

  1. 在您app.js或每个文件中声明这些名称空间(由于缺乏更好的用语);
  2. 请参考每个文件中的那些名称空间。

因此,您app.js将如下所示:

angular.module('myApp', ['external-dependency-1', 'myApp.services', 'myApp.controllers'])
.run(function() {
   //...

})
.config(function() {
  //...
});

并在每个文件中:

services.js

angular.module('myApp.services', []); //instantiates
angular.module('myApp.services') //gets
.factory('MyService', function() { 
  return {};
});

controllers.js

angular.module('myApp.controllers', []); //instantiates
angular.module('myApp.controllers')      //gets
.controller('MyCtrl', function($scope) {
  //snip...
})
.controller('AccountCtrl', function($scope) {
  //snip...
});

所有这些都可以合并为一个调用:

controllers.js
angular.module('myApp.controllers', []) 
.controller('MyCtrl', function($scope) {
 //snip...
});    

重要的是您不应重新定义angular.module('myApp'); 实例化控制器时可能会覆盖它,可能不是您想要的。


1
我喜欢这种方法,您可以使用它来创建分层结构(例如您的控制器需要服务或过滤器)。注意,我还发现,一旦注入了一个子依赖关系(例如控制器的过滤器),上面的所有父级(如果可视化为树)都可以使用它,而无需重新声明注入,只是不要如果您更换孩子并在父母中使用它,请不要忘记它。我也建议不要在一个文件中放置多个模块(命名空间),也不要在多个文件中尝试使用相同的命名空间。
加里

如果我有两个控制器文件或两个服务文件怎么办?实例化会针对每个单个文件进行吗?
Avinash Raj

3

您收到错误是因为尚未定义myApp.services。到目前为止,我所做的就是将所有初始定义放在一个文件中,然后在另一个文件中使用它们。就像您的示例一样,我将输入:

app.js

angular.module('myApp.services', []);

angular.module('myApp', 
    ['myApp.services',
      ...]);

尽管我认为您应该阅读其中一条评论中提到的Eduard Gamonal文章,但这应该可以消除错误。


谢谢,Torsten,但我已阅读该文章并将该行添加angular.module('myApp.services', []);到我的app.js文件中。都没有真正解决我的问题。
ChrisDevo 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.