1

以这种方式使用 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"];

这将导致错误:

错误:[$injector:unpr] 未知提供者:$scopeProvider <- $scope

这是一个展示错误的示例的plunker,请查看评论以获取替代方案,以查看只有范围而非自定义服务受此影响。
我发现了这个Angular 错误,他们谈到在创建子 $scope 之前实例化控制器,正如Tomer Avni回答的那样,所以:

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

1 回答 1

1

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


当你给 Angular 一个函数调用时,它的值将来自依赖注入(例如服务、控制器等),Angular 将:

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

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

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

在它工作的示例中,您不是直接访问注入器,而是依靠 Angular 来确定如何创建控制器。这是一个微妙的区别,但在这种情况下是一个重要的区别。在 Angular 中,当创建控制器实例时,它将解析$scope为调用的结果$rootScope.$new()(即在单元测试中手动实例化控制器时会做什么)。

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

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

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

但是现在我们开始走上一条非常模糊的道路……$injector直接注入是非常不典型的。如果可以的话,我会避免这种情况。你有理由这样做吗?

于 2016-02-15T14:17:03.300 回答