错误未知提供者:$scopeProvider <- $scope 使用 $injector 将 $scope 注入控制器时

Error Unknown provider: $scopeProvider <- $scope when using $injector to inject $scope into controller

以这种方式使用 DI 时:

var MainController = function MainController($scope) {
  //use $scope here
};
MainController.$inject = ["$scope"];

它可以工作,但是,当它像这样使用时:

var MainController = function MainController($injector) {
  var $scope = $injector.get("$scope");
};
MainController.$inject = ["$injector"];

这将导致错误:

Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope

这里有一个 plunker 示例,其中包含一个展示错误的示例,请查看注释以了解替代方案,以了解只有范围而非自定义服务受此影响。
我发现这个 Angular bug where they talk about the controller being instantiated before the child $scope is being created as Tomer Avni 已回答,所以:

  1. 为什么第一种注入方式 $scope 有效而第二种注入方式无效?
  2. 还有没有办法使用依赖注入的第二种方法 用 $injector 注入 $scope?

我已经在 gitter 上回复了你,但在这里回答以及它可能会帮助其他有同样问题的人。


当您给 Angular 一个函数调用时,该函数的值将从依赖注入(例如服务、控制器等)派生,Angular 将:

  • 在函数对象上寻找 .$inject 属性,它应该是依赖名称作为字符串的数组(例如 ['$scope'])。
  • 如果 $inject 未定义,它将使用函数定义的参数(这在大多数情况下有效,除非您缩小代码并且名称被破坏)。

因此,简而言之,它将查找您在 DI 容器中指定的名称。

$scope 在 DI 容器中不存在 ,只有 $rootScope 存在。因此,如果您直接访问注入器并请求 $scope 的实例,您将得到您在此处看到的注入错误。

在它起作用的示例中,您没有直接访问注入器,而是依赖于 Angular 计算如何创建您的控制器。这是一个细微的差别,但在这种情况下是一个重要的差别。在 Angular 中,当创建控制器实例时,它会将 $scope 解析为调用 $rootScope.$new() 的结果(即在单元测试中手动实例化控制器时您将执行的操作)。

我希望这能解释为什么您的示例不起作用。

关于第二个问题,您可以通过执行以下操作手动获取作用域实例:

var $scope = $injector.get('$rootScope').$new();

但现在我们开始走上一条相当阴暗的道路......直接注入 $injector 是非常不典型的。如果可以的话,我会避免这种情况。您是否需要这样做?