在AngularJS控制器定义中是$ scope依赖注入吗?

时间:2015-02-02 22:27:41

标签: angularjs dependency-injection

所有

让我对AngularJS中的依赖注入感到困惑的是它的概念(我想我还没有完全了解DI):

我想知道如何判断应该(并且可以)注入哪些依赖项?

例如:

如果我定义了一个控制器和指令:

app.controller("maincontroller", ["$scope", "dependency1", function($scope, dependency1){

}])

app.directive("dir1", ["dependency2", "dependency3", 
                       function(dependency2, dependency3){
    return {
         restrict: "AE",
         scope:{},
         controller: function($scope){},
         link:function(scope, EL, attrs, ctrl){}
    };
}]) 

我想知道为什么我需要在控制器中注入$ scope作为依赖项,但是在指令定义中不需要这样做。更重要的是:如果我将$ scope放在该指令函数中,它会给我一个错误:

Error: error:unpr
Unknown Provider
Unknown provider: $scopeProvider <- $scope <- dir1Directive

[1] 这个$ scope是依赖项,还是 [2] 我对依赖项的理解是完全错误的(有人告诉我$ scope不是依赖项)或 [3] 我对指令def函数的理解是错误的(只有服务可以放在指令def函数中)?

如果我的错误是最后一个,那么AngularJS有多少种依赖关系?

由于

1 个答案:

答案 0 :(得分:4)

$scope实际上并不是一项服务!

这就是为什么你不必将它作为指令的依赖项传递的原因。 $scope是传递给注入器的本地,一个传递给函数的值,就好像我会console.log(myValue)一样。 myValue不是服务。

$injector invoke方法将服务传递给函数,可以用给定的值替换请求的依赖关系,有关详细信息,请参阅the docs。我认识到参数列表中的混合服务和简单​​值是混乱的,因为我们无法知道哪一个是服务,哪一个是简单的参数,但它是这样的。

我们可以考虑在实现新控制器时执行类似的操作:

var $rootScope = $injector.get('$rootScope');
$injector.invoke(controller, context /*the this binding*/, {
    $scope: $rootScope.new()
});

有关详细信息,另请参阅the code of the controller service

更新:$scope和服务

之间的差异

采取此功能:

function add(a, b) {
    return a + b;
}

ab是&#34;简单参数&#34;,它们是函数执行计算的值。想象一下,您想要向您的应用广播一条消息,表明已经执行了添加。在Angular中,我们可以使用$rootScope.$broadcast方法。

function add(a, b) {
    $rootScope.$broadcast('addition.done', a + b);
    return a + b;
}

但是在这里,$rootScope从未被宣布过。我们必须在我们的函数中加载$rootScope服务。 Angular使用$injector.invoke方法来执行此操作:它采用函数或数组(&#34;方括号&#34;表示法),从函数中提取服务名称 arguments / array elements,使用作为参数传递的相应服务调用该函数。

function add(a, b, $rootScope) {
    $rootScope.$broadcast('addition.done', a + b);
    return a + b;
}

var $injector = angular.injector(['ng']); // Creates the injector, with the services of `ng` module.
$injector.invoke(add); // Calls the function with the requested services

它会引发错误,因为ab不是服务。事实上,他们不必是服务,因为他们是我们想要自己设定的价值观。对于注射器,它们是当地人。为了使用2函数添加3add,我们必须执行以下操作:

function add(a, b, $rootScope) {
    $rootScope.$broadcast('addition.done', a + b);
    return a + b;
}

var $injector = angular.injector(['ng']);
$injector.invoke(add, this, {
    a: 2, // When requesting the `a` service, return the value `2`
    b: 3 // The same here, with `b` and `3`
});

控制器也是如此。 $scope本身不是服务,而是每次加载指令时构建的新范围。与ab类似,新创建的$scope一个值,函数在该值上执行某些逻辑和修改 $scope不是依赖项,而是函数的参数。并且因为$injector从参数列表中提取依赖项,我们无法判断参数是否存在是服务与否(除非您已经知道,但这不是证据)。这里,$scope 不是服务,也是指令中link函数中的对象。请注意,文档未将范围参数命名为$scope,而是scope。如果scope是一项服务,则会产生错误,但事实上并非如此,因为link函数未被$injector.invoke调用。