子控制器是否继承了对服务的访问权限?

Is access to a service inherited by child controllers?

如果父控制器注入了服务,控制器的子控制器是隐式继承服务还是必须显式注入服务?

您需要显式注入服务。子控制器继承作用域,当然服务不在作用域对象上(除非你把它放在那里)

查看这个 jsfiddle 来证明这一点:http://jsfiddle.net/HB7LU/11596/

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

myApp.factory('serviceId', function() {
  var a = 1;
    return {
        a: a
    };
});

myApp.controller('Ctrl',['$scope', 'serviceId' ,function($scope, serviceId) {
    $scope.name = 'Superhero' + serviceId.a;
}])

myApp.controller('ChildCtrl',['$scope',function($scope) {

    // the next line throws an undefined error because of serviceId
    $scope.name = 'Superhero' + serviceId.a;
}])

如果您进行原型继承,那么您可以从父控制器中获得一个字段,作为可以在派生控制器中使用的东西。为了使 angular js 控制器可继承,你必须做一些事情。希望下面的解释会更清楚。

JavaScript

中的原型继承

因此,首先让我们定义我们将如何以原型方式从对象继承。在javascript中,原型继承可以按如下方式进行:

function Foo(some_param)
{
    this.some_param = some_param
}

function Bar(some_param, some_specialized_param)
{
    /**
     * Call the super class constructor
     */
    Foo.call(this, some_param);
    this.some_specialized_param = some_specialized_param;
}

/**
 * Now that you have defined the constructor, you need to
 * define the prototypical inheritance
 */
Bar.prototype = Object.create(Foo.prototype);

/**
 * Now you have to set the constructor
 */ 
Bar.prototype.constructor = Bar;

所以使用这个例子你可以创建 angularjs 控制器。然而有一个问题。例如,如果 class 栏位于不同的模块或目录中,则需要导入定义。您可以使用一些其他工具,如 RequireJS,在定义 Bar 的文件中加载 module/controller/class 定义,然后按如下方式继承。但是,您也可以使用 angularjs 结构,如下所示:

AngularJS

中的控制器继承

因此您可以使用两个 angularjs 构造来定义控制器的实例化点(angular.module(..).constructor)和控制器的定义(angular.module(. 。)。工厂)。 AngularJS 工厂可用于控制器的 class 定义。

angular.module('some_module')
.factory('BaseCtrlClass', ['aService', function(aService)
{
    function BaseCtrl($scope)
    {
        /**
         * Assign a reference to "aService"
         * which is injected whithin this factory
         */
        this.aService = aService;
        this.$scope = $scope;
    }

    return BaseCtrl;
}]);

现在您可以定义一个控制器定义,以便您可以使用 ngController 对其进行实例化,例如:

angular.module('some_module')
.controller('BaseCtrl', [$scope, 'BaseCtrlClass', function($scope, BaseCtrlClass)
{
    return new BaseCtrlClass($scope);
}]);

请注意,在工厂中我将其定义为 BaseCtrlClass,因为那是 class 定义。在控制器构造中,我定义了 BaseCtrl,您可以像使用 ngController 提到的那样在外部使用它。 BaseCtrlClass 名称应该在派生控制器内部使用,我们将在下面看到。因此,正如我提到的,当您尝试在另一个 file/module 中导入 BaseCtrlClass 的定义时,问题就来了,最好是定义 DerivedCtrl class 的文件。让我们定义 DerivedCtrl Class 如下:

angular.module('a_different_module')
.factory('DerivedCtrlClass', ['BaseCtrlClass', function(BaseCtrlClass)
{
    function DerivedCtrl($scope, aDifferentService)
    {
        BaseCtrlClass.call(this, $scope);
        this.aDifferentService = aDifferentService //Specialized resource
    }

    DerivedCtrl.prototype = Object.create(BaseCtrlClass.prototype);
    DerivedCtrl.prototype.constructor = DerivedCtrl;        

    return DerivedCtrl; 
}])
.controller('DerivedCtrl', ['$scope', 'aDiferentService', 'DerivedCtrlClass', function($scope, aDifferentService, DerivedCtrlClass)
{
    return new DerivedCtrlClass($scope, aDifferentService);
}]);

所以在这里你可以看到我在一个名为 DerivedCtrlClass 的工厂中定义了 DerivedCtrl。这实质上定义了控制器 class 定义。所以任何其他模块或 class 试图从这里继承都可以利用这个工厂。在构造函数中,我调用了 BaseCtrlClass 的构造函数,并根据需要将 "this" 和“$scope”作为参数传递。后来我定义了原型构造和默认构造函数,类似于我之前提到的 javascript 示例。为了方便起见,我也定义了一个控制器结构,它也可以与 ngController 一起使用。

我想强调的重点是 DerivedCtrl 的实例现在可以使用

this.aService

这是在 BaseCtrl 中定义的东西。基本上,在 BaseCtrl 和 DerivedCtrl 的范围内定义的任何内容现在都可以在 DerivedCtrl 的实例中使用。当您尝试定义 DerivedCtrl 时,这在 html 中非常有效,您可以这样做

<div ng-controller="DerivedCtrl">
    ......
</div>

作用域继承

如果你想有作用域继承,你可以使用这样的东西:

<div ng-controller="BaseCtrl">
    <div ng-controller="DerivedCtrl">
        ...
    </div>
</div>

问题在于您需要使用 $scope 来传递字段。在 BaseCtrl 的构造函数中,您需要执行以下操作:

$scope.aService = aService

然后您可以从 DerivedCtrl 使用 $scope.aService。这不是很好,因为它破坏了封装。为了可维护性,您可能不希望导出此服务并使其伪保护仅供从 BaseCtrl 继承的 classes 访问。这样的话我提供的方案就很好用了,至少我一直在用这种方式。

希望这对您有所帮助。