我有一个服务,说:
factory('aService', ['$rootScope', '$resource', function ($rootScope, $resource) {
var service = {
foo: []
};
return service;
}]);
我想用foo来控制一个在HTML中呈现的列表:
<div ng-controller="FooCtrl">
<div ng-repeat="item in foo">{{ item }}</div>
</div>
以便控制器检测aService。我已经拼凑了这个模式,其中我添加aService到控制器的$scope,然后使用$scope.$watch():
function FooCtrl($scope, aService) {
$scope.aService = aService;
$scope.foo = aService.foo;
$scope.$watch('aService.foo', function (newVal, oldVal, scope) {
if(newVal) {
scope.foo = newVal;
}
});
}
这感觉有点冗长,我一直在每个使用服务变量的控制器中重复这一点。有没有更好的方法来监视共享变量?
我在另一个线程上找到了一个非常好的解决方案,有类似的问题,但方法完全不同。当$rootScope值被改变时,$watch within指令将无法正常工作
基本上解决方案告诉不要使用$watch,因为它是非常沉重的解决方案。相反,他们建议使用$emit和$on。
我的问题是在我的服务中观察一个变量并在指令中做出反应。用上面的方法就很简单了!
我的模块/服务示例:
angular.module('xxx').factory('example', function ($rootScope) {
var user;
return {
setUser: function (aUser) {
user = aUser;
$rootScope.$emit('user:change');
},
getUser: function () {
return (user) ? user : false;
},
...
};
});
所以基本上我观察我的用户-每当它被设置为新值时I $emit一个user:change status。
在我的例子中,在我使用的指令中:
angular.module('xxx').directive('directive', function (Auth, $rootScope) {
return {
...
link: function (scope, element, attrs) {
...
$rootScope.$on('user:change', update);
}
};
});
现在在指令中,我监听$rootScope和给定的更改-我分别做出反应。非常简单和优雅!
有点丑,但我已经为切换添加了范围变量的注册到我的服务:
myApp.service('myService', function() {
var self = this;
self.value = false;
self.c2 = function(){};
self.callback = function(){
self.value = !self.value;
self.c2();
};
self.on = function(){
return self.value;
};
self.register = function(obj, key){
self.c2 = function(){
obj[key] = self.value;
obj.$apply();
}
};
return this;
});
然后在控制器中:
function MyCtrl($scope, myService) {
$scope.name = 'Superhero';
$scope.myVar = false;
myService.register($scope, 'myVar');
}
我在另一个线程上找到了一个非常好的解决方案,有类似的问题,但方法完全不同。当$rootScope值被改变时,$watch within指令将无法正常工作
基本上解决方案告诉不要使用$watch,因为它是非常沉重的解决方案。相反,他们建议使用$emit和$on。
我的问题是在我的服务中观察一个变量并在指令中做出反应。用上面的方法就很简单了!
我的模块/服务示例:
angular.module('xxx').factory('example', function ($rootScope) {
var user;
return {
setUser: function (aUser) {
user = aUser;
$rootScope.$emit('user:change');
},
getUser: function () {
return (user) ? user : false;
},
...
};
});
所以基本上我观察我的用户-每当它被设置为新值时I $emit一个user:change status。
在我的例子中,在我使用的指令中:
angular.module('xxx').directive('directive', function (Auth, $rootScope) {
return {
...
link: function (scope, element, attrs) {
...
$rootScope.$on('user:change', update);
}
};
});
现在在指令中,我监听$rootScope和给定的更改-我分别做出反应。非常简单和优雅!
您可以在工厂内部观察更改,然后广播更改
angular.module('MyApp').factory('aFactory', function ($rootScope) {
// Define your factory content
var result = {
'key': value
};
// add a listener on a key
$rootScope.$watch(function () {
return result.key;
}, function (newValue, oldValue, scope) {
// This is called after the key "key" has changed, a good idea is to broadcast a message that key has changed
$rootScope.$broadcast('aFactory:keyChanged', newValue);
}, true);
return result;
});
然后在你的控制器中:
angular.module('MyApp').controller('aController', ['$rootScope', function ($rootScope) {
$rootScope.$on('aFactory:keyChanged', function currentCityChanged(event, value) {
// do something
});
}]);
通过这种方式,您将所有相关的工厂代码放在其描述中,然后您只能依赖来自外部的广播
如果您想避免$watch的暴政和开销,您总是可以使用老式的观察器模式。
在服务中:
factory('aService', function() {
var observerCallbacks = [];
//register an observer
this.registerObserverCallback = function(callback){
observerCallbacks.push(callback);
};
//call this when you know 'foo' has been changed
var notifyObservers = function(){
angular.forEach(observerCallbacks, function(callback){
callback();
});
};
//example of when you may want to notify observers
this.foo = someNgResource.query().$then(function(){
notifyObservers();
});
});
在控制器中:
function FooCtrl($scope, aService){
var updateFoo = function(){
$scope.foo = aService.foo;
};
aService.registerObserverCallback(updateFoo);
//service now in control of updating foo
};