您有一个名为“ DataService ”的服务,其中包含一个关闭 可以通过get / set / display(ClosurePropertyName)获取/设置/显示闭包属性:
var app = angular.module('app',[]);
app.service('DataService', [function(){
var data = this;
(function initialize() {
var closure = {
prop: 'etc',
otherProp: [],
diffProp: {
a: 'b',
c: 'd'
}
}, keys = Object.keys(closure);
// ex: data.displayProp()
// returns : Displaying etc
data.displayProp = function () {
return 'Displaying: ' + closure.prop;
}
// ex: data.getProp()
// returns : etc
data.getProp = function () {
return closure.prop;
}
// ex: data.setProp("derp");
// becomes: closure.prop = "derp"
data.setProp = function (val) {
closure.prop = val;
}
data.allProps = function () {
var obj = {};
for (var i = 0; i < keys.length; i++) {
obj[keys[i]] = closure[keys[i]];
}
return obj;
}
})();
}]);
您有控制器访问此服务:
app.controller('CntrlA', ['$scope', 'DataService', function($scope, DataService){
var props = DataService.allProps();
this.props = props;
this.changeProp = function(val){
DataService.setProp(val);
}
$scope.CntrlA = this;
return $scope.CntrlA;
}]);
app.controller('CntrlB', ['$scope', 'DataService', function($scope, DataService){
var props = DataService.allProps();
this.changeOtherProps = function(arr){
DataService.setOtherProp(arr);
}
$scope.CntrlB = this;
return $scope.CntrlB
}]);
简单的html:
body[ng-app="app"]
div[ng-controller="CntrlA as aa"]
button[ng-click="aa.changeProp('herp a derp')"]
div "{{aa.props}}"
div[ng-controller="CntrlB as bb"]
button[ng-click="bb.setOtherProp(['all', 'the', 'things'])"]
div "{{bb.props}}"
当值发生变化时,如何更改以应用于两者?我知道这必须简单,但是$ scope。$ watch不起作用。
答案 0 :(得分:1)
在这种情况下使用$watch
看起来像这样:
$scope.$watch(function() {
return DataService.allProps();
},
function(newValue, oldValue) {
if (newValue === oldValue) return;
$scope.CntrlA.props = newValue;
}, true);
由于allProps
每次都返回一个新的对象引用,因此需要传递true
作为第三个参数。否则你将获得&#34; Infinite $ digest循环&#34; -error。
但是,在这种情况下使用$watch
根本不会有效。每个摘要循环包含多个摘要循环,每个循环将执行DataService.allProps()
并在其中执行迭代。由于您必须将true
作为第三个参数传递给$watch
,因此它将在内部使用angular.equals
和angular.copy
,这涉及更昂贵的操作。
使用$watch
进行演示(取消控制台): http://plnkr.co/edit/DLmT5XAPBXA3dg5DENRS?p=preview
如果您的服务需要看起来像这样,更好的解决方案是在每次属性更改时触发事件。这样,摘要周期就不会有负担。
例如:
data.setProp = function(val) {
closure.prop = val;
$rootScope.$emit('DataService:update');
};
在控制器中:
var unregister = $rootScope.$on('DataService:update', function() {
$scope.CntrlA.props = DataService.allProps();
});
$scope.$on('$destroy', unregister);
使用$ emit进行演示: http://plnkr.co/edit/QfdqGsLVXYnL4HIy82gk?p=preview