Angularjs 指令内异步服务处理程序中的作用域修改后未更新DOM

Angularjs 指令内异步服务处理程序中的作用域修改后未更新DOM,angularjs,angularjs-directive,angularjs-scope,Angularjs,Angularjs Directive,Angularjs Scope,我的指令调用一些基于$http的异步服务。服务名称作为参数出现在derectiva中: .directive('lookup', ['$scope', function($scope, svc) { var injector = angular.injector(['app', 'ng']); var svc = injector.get(scope.serviceName); ... $scope.clickHandler = function () { svc.

我的指令调用一些基于$http的异步服务。服务名称作为参数出现在derectiva中:

.directive('lookup', ['$scope',  function($scope, svc) {

  var injector = angular.injector(['app', 'ng']);
  var svc = injector.get(scope.serviceName);
  ...
  $scope.clickHandler = function () {

    svc.lookup($scope.inputText).then(function (res) {

      $scope.inputText = res.data.name;
    });
  }
  ...
})
then()
处理程序中设置chrome断点时,我们可以通过调用堆栈看到它是在
$apply()
中触发的,因此每个范围更改都应该反映在DOM中$q文档还指出,处理程序应该与scope/dom更新周期同步,但在
clickHandler()
之后,我的视图不会更新。在范围更改后调用显式的
scope.$digest()
,可以做到这一点,但不知道没有它为什么不起作用。我注意到的另一件奇怪的事情是,在断点上,
$scope
$rootScope
没有父子关系,http响应处理程序由
$apply()
包装。也许这就是我烦恼的原因。我做错什么了吗

真正的代码很难引用,但请参见

说明中的基本示例代码: 这件作品的反面是在链接功能中使用了
angular.injector

var injector = angular.injector(['ng', 'app']);
var lookupService = injector.get(scope.serviceName);
此代码将创建一个新的注入器函数,而不是在应用程序启动时检索已创建的注入器函数

Angular中的服务是单例的,因为每个注入器只创建一次。在您的情况下,这意味着
injector.get(scope.serviceName)
将返回一个新的服务实例,而不是您以前可能与之交互的实例

您的
lookupService
使用的
$http
服务也是如此。反过来,
$http
注入
$rootScope
,通过在XHR请求后对其调用
$apply
来触发摘要循环。但是由于
$rootScope
与应用程序的其余部分不同,摘要周期将是徒劳的

这也是您看到的行为的原因,也是为什么显式调用
scope.$digest()
会有帮助,因为它会在正确的作用域链上触发摘要循环

解决方案: 在指令中插入
$injector
服务,并使用该服务检索所需的服务:

.directive('lookup', ['$injector',
  function($injector) {
    function link(scope, elem) {

      var lookupService = $injector.get(scope.serviceName);

演示:

如何调用
$scope.clickHandler
呢?plunker\jshiddle或者它没有发生。:)真的发生了:)-看普朗克斯,回答得很好。您的回复将有关angularjs注入器、服务和$rootScope的重要信息作为单例。谢谢