Angularjs 指令内异步服务处理程序中的作用域修改后未更新DOM
我的指令调用一些基于$http的异步服务。服务名称作为参数出现在derectiva中: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.
.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的重要信息作为单例。谢谢