对AngularJS依赖注入不一致感到困惑

时间:2014-07-29 16:30:54

标签: javascript angularjs

我是angular.js的新手,并经历了几个教程,包括 codeschool 上的所有教程。我发现它们非常有用,并且学到了很多东西。但是现在我已经完成了我的“介绍”并开始尝试在某些方面使用它,我发现了一些令人困惑的不一致,最明显的是“依赖注入”。

在我参考的教程中,服务的依赖关系是这样完成的;

app.controller('name', [ $http, $scope, function($http, $scope) {
   // .. code ... //
}]);

这让我感到很奇怪,但无论如何它仍然有效。我很困惑为什么[]在函数之前没有终止(我强<假> 这就是你所说的'回调'函数JavaScript的?)。我期待它更像require.js本来就是......

app.controller('name', [ '$http', '$scope' ], function($http, $scope) { });

然而,我开始查看角度在线的示例和演示,我发现这不一致。例如,检查以下链接;

在每一个中,我都看到依赖注入像这样使用;

app.controller('name', function($http, AdvancedGithubUser) { });
app.controller('name', function($scope){ });
function controllerName($scope) { };

他们完全绕过array类似的语法,三者都不同。在一个,它需要一种在其他地方声明的对象,但我没有看到任何布线指向它。

另一方面,它只是有这些对象。

仍然在另一个中,controller的'name'部分是函数的名称,我没有看到任何真正表示为controller的东西,但它在指令。

任何人都可以向我解释这个吗?我现在完全迷失了。这种不一致使得采用这些技术有点困难。

3 个答案:

答案 0 :(得分:6)

有三种方法可以注释函数的依赖关系:

第一个是:使用参数名称显式且准确:

app.controller('ACtrl', function($scope, $http, $q) {
    //your stuff here
});

这意味着该函数具有必须与已注册的服务/提供者的名称匹配的参数名称。 警告:如果你缩小文件(uglify,以节省空间),你将丢失参数名称,因此它将被破坏 - 不起作用(会抱怨)。

第二个允许您选择要作为字符串文字注入的服务名称(因为字符串文字是一个值,它永远不会缩小):

var myfunc = function($s, $http, $q) {
    //do your stuff here
};
myfunc.$inject = ['$scope', '$http', '$q'];
app.controller('ACtrl', myfunc);

这使Angular读取函数的$ inject属性,并且不是按名称匹配形式参数,而是按相同数组位置的值匹配。因此,即使您缩小文件,$ scope也将以$ s为单位。如果函数中不存在$ inject,那么你将回到第一个 - 而不是推荐 - 的情况。

第三个类似于第二个(即它将通过字符串指定依赖关系并且将抵制丑化):

var myfunc = function($s, $http, $q) {
    //do your stuff here
}
app.controller('ACtrl', ['$scope', '$http', '$q', myfunc]);

请注意,数组的最后一个元素是要调用的函数。它看起来有点令人毛骨悚然,但它是一致的。 Angular这样做:如果控制器是一个数组,则弹出最后一个元素 - 它将是函数。前面的元素(剩下的数组)与函数中的$inject值完全相同。

控制器和提供者必须有一个名称来引用它们 - 我使用'ACtrl'作为控制器的名称。它不是函数的名称,而是在依赖注入(对于提供者)和诸如ngRoute(对于控制器)之类的东西中使用的内部名称。

声明名称是您要求的接线的第一个界限。在三种形式的依赖注入中使用它们是这种布线的第二种结合。

记住AdvancedGithubUser是注册提供商,$http也是如此。唯一的区别是$http内置在Angular中,而AdvancedGithubUser不是。美元符号起始符号应该保留给Angular,但这不是一个要求 - 只是一个好习惯。 AdvancedGithubUser已创建(在外部模块中),类似于:

app.service('AdvancedGithubUser', AdvancedGithubUser);
//being AdvancedGithubUser a constructor.

答案 1 :(得分:4)

两个

myApp.controller('ACtrl', ['$scope', function($scope) { }])

myApp.controll('ACtrl', function($scope) { });

是允许的。但是,根据docs,建议使用第一种方法(数组表示法)。

  

“这可以避免为控制器创建全局函数,也可以防止缩小”。

答案 2 :(得分:1)

您可以使用直接依赖注入(如链接)或命名依赖注入(使用数组)。

我建议将命名语法作为最小化器,例如uglify将压缩变量名称。使用数组,您可以将对象命名为inject,然后将(最后一个参数,函数)命名为您使用它,因此在变量压缩后,angular仍将知道您想要的对象。