如何创建单独的AngularJS控制器文件?


315

我将所有AngularJS控制器都放在一个文件controllers.js中。该文件的结构如下:

angular.module('myApp.controllers', [])
  .controller('Ctrl1', ['$scope', '$http', function($scope, $http) {    
  }])
  .controller('Ctrl2', ['$scope', '$http', function($scope, $http) }
  }])

我想做的是将Ctrl1和Ctrl2放入单独的文件中。然后,我会将这两个文件都包含在index.html中,但是应该如何构造呢?我试图做这样的事情,它在网络浏览器控制台中抛出一个错误,提示找不到控制器。有什么提示吗?

我搜索了StackOverflow,发现了类似的问题-但是,此语法在Angular的顶部使用了不同的框架(CoffeeScript),因此我无法遵循。


AngularJS:如何在多个文件中创建控制器

Answers:


399

文件一:

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

文件二:

angular.module('myApp.controllers').controller('Ctrl1', ['$scope', '$http', function($scope, $http){

}]);

文件三:

angular.module('myApp.controllers').controller('Ctrl2', ['$scope', '$http', function($scope, $http){

}]);

按该顺序包括。我建议使用3个文件,因此模块声明是独立的。


至于文件夹的结构,在这个问题上有很多很多观点,但是这两个都很好

https://github.com/angular/angular-seed

http://briantford.com/blog/huuuuuge-angular-apps.html


1
如果OP表示对CoffeeScript语法感到困惑,也许最好不要在答案中使用它?
安德鲁(Andrew)

3
@Andrew imho未来的帮助并记录解决方案是SO真正的目的,而不是临时的问与答。
Fresheyeball 2014年

2
@RuslanIsmagilov您appCtrl是全球性的window.appCtrl。这不是一个好习惯。
Fresheyeball 2014年

1
@Fresheyeball,此方法的问题在于index.html中的导入顺序很重要,否则,Angular会发出错误。
Deoxyseia 2014年

2
@hendryau,好吧,我正在使用OP中存在的模块名称。也就是说,有些人认为在组织上最好有多个以名称分隔的模块,而不是中央应用程序模块。
Fresheyeball 2015年

177

将angular.module API 与最后一个数组一起使用将告诉angular创建一个新模块:

myApp.js

// It is like saying "create a new module"
angular.module('myApp.controllers', []); // Notice the empty array at the end here

在没有数组的情况下使用它实际上是一种吸气功能。因此,要分离控制器,您可以执行以下操作:

Ctrl1.js

// It is just like saying "get this module and create a controller"
angular.module('myApp.controllers').controller('Ctrlr1', ['$scope', '$http', function($scope, $http) {}]);

Ctrl2.js

angular.module('myApp.controllers').controller('Ctrlr2', ['$scope', '$http', function($scope, $http) {}]);

在您导入JavaScript期间,只需确保myApp.js在AngularJS之后但在任何控制器/服务/等之前...否则,angular将无法初始化您的控制器。


我应该在哪里写我的依赖项。var myapp = angular.module('demo',['ngRoute','ngCookies','ui.bootstrap','nvd3ChartDirectives','ui-rangeSlider','textAngular','angularTreeview']);;
vipin 2014年

@vipin就像您键入的内容一样,但是请确保它位于任何控制器,服务等之上。从技术上讲,您无需声明var myapp = ...; 因为angular会为您存储它。
Jimmy Au

@JimmyAu Ctrl1.js和Ctrl2.js在哪里加载,以便页面可以使用它?我刚在angular之后加载了myApp.js,但是页面找不到控制器。我是否必须在需要它的视图上将它们明确添加为脚本?还是我仍然必须在每个页面上包含每个控制器文件?
Sinaesthetic,2015年

2
感谢您澄清为什么只有第一个通话需要[]。
Jim B.

49

尽管两个答案在技术上都是正确的,但我想为此答案引入不同的语法选择。这个恕我直言让您更轻松地了解注射过程,区分等。

文件一

// Create the module that deals with controllers
angular.module('myApp.controllers', []);

文件二

// Here we get the module we created in file one
angular.module('myApp.controllers')

// We are adding a function called Ctrl1
// to the module we got in the line above
.controller('Ctrl1', Ctrl1);

// Inject my dependencies
Ctrl1.$inject = ['$scope', '$http'];

// Now create our controller function with all necessary logic
function Ctrl1($scope, $http) {
  // Logic here
}

文件三

// Here we get the module we created in file one
angular.module('myApp.controllers')

// We are adding a function called Ctrl2
// to the module we got in the line above
.controller('Ctrl2', Ctrl2);

// Inject my dependencies
Ctrl2.$inject = ['$scope', '$http'];

// Now create our controller function with all necessary logic
function Ctrl2($scope, $http) {
  // Logic here
}

有趣的是,它的确使我无需去多个文件来注册控制器
mrwaim 2015年

4
我看到很多这样的编码。有什么好处?$ inject和一个函数分开的过程。
Alaksandar Jesus Gene 2015年

2
我相信它使代码更易于阅读。我知道到底注射了什么。逐行将其视为“关注点分离”。
jason328

2
这样的代码不仅产生更可读的代码,是更易于调试,并降低的嵌套回调代码(见量github.com/johnpapa/angular-styleguide/blob/master/a1/...
rfornal

如果我能为此1000次+1,那就太好了!
丹·蔡斯

17

那这个解决方案呢?文件中的模块和控制器(在页面末尾)它可与多个控制器,指令等配合使用:

app.js

var app = angular.module("myApp", ['deps']);

myCtrl.js

app.controller("myCtrl", function($scope) { ..});

html

<script src="app.js"></script>
<script src="myCtrl.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">

Google还提供了有关Angular应用程序结构最佳实践建议, 我真的很喜欢按上下文进行分组。不是一个文件夹中的所有html,而是例如所有用于登录的文件(html,css,app.js,controller.js等)。因此,如果我在模块上工作,所有指令都更容易找到。


3

为简便起见,这是一个不依赖全局变量的ES2015示例

// controllers/example-controller.js

export const ExampleControllerName = "ExampleController"
export const ExampleController = ($scope) => {
  // something... 
}

// controllers/another-controller.js

export const AnotherControllerName = "AnotherController"
export const AnotherController = ($scope) => {
  // functionality... 
}

// app.js

import angular from "angular";

import {
  ExampleControllerName,
  ExampleController
} = "./controllers/example-controller";

import {
  AnotherControllerName,
  AnotherController
} = "./controllers/another-controller";

angular.module("myApp", [/* deps */])
  .controller(ExampleControllerName, ExampleController)
  .controller(AnotherControllerName, AnotherController)

1
如果您使用命名函数,则可以节省很多键入操作。.它们具有方便的属性name..因此,您可以简单地使用ExampleCtrl.name而不是重复。
Antti Pihlaja

0

不是那么优美,但是实现解决方案非常简单-使用全局变量。

在“第一个”文件中:


window.myApp = angular.module("myApp", [])
....

在“第二”,“第三”等中:


myApp.controller('MyController', function($scope) {
    .... 
    }); 

我使用此代码,但仍然无法加载我的控制器?它抛出错误:错误:[ng:areq]参数'ProductCtrl'不是一个函数,未定义。
QViet

7
这确实是不好的做法
Brendan

@Kim Jong Un如果不将控制器添加/连接到您创建的模块,则会看到该错误。因此,如果您使用以下语法,它将可以正常工作:angular.module('myApp').controller('ProductCtrl', ['$scope', '$http', function($scope, $http){ //Your ProductCtrl code goes here }]);
Devner's

1
@Brendan,简单地说一些不好的做法总比没有好,但没有多大作用。告诉我们为什么不好的做法会帮助别人。
Mawg说恢复Monica's 17-10-9
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.