我有一个服务,说:

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中插入服务,然后观察:

myApp.run(function($rootScope, aService){
    $rootScope.aService = aService;
    $rootScope.$watch('aService', function(){
        alert('Watch');
    }, true);
});

在你的控制器中:

myApp.controller('main', function($scope){
    $scope.aService.foo = 'change';
});

另一个选择是使用外部库,例如:https://github.com/melanke/Watch.JS

"发射架:IE +, f4 +,稳定基金5+

您可以观察一个、多个或所有对象属性的变化。

例子:

var ex3 = {
    attr1: 0,
    attr2: "initial value of attr2",
    attr3: ["a", 3, null]
};   
watch(ex3, function(){
    alert("some attribute of ex3 changes!");
});
ex3.attr3.push("new value");​

其他回答

我在这里看到过一些可怕的观察者模式,它们会在大型应用程序上导致内存泄漏。

我可能会来晚一点,但就是这么简单。

如果你想查看数组推送之类的东西,可以使用watch函数查看引用更改(基本类型):

someArray.push(someObj);someArray = someArray.splice(0);

这将从任何地方更新引用和手表。包括一个服务getter方法。 任何原语都将被自动更新。

// service:(这里没有什么特别的)

myApp.service('myService', function() {
  return { someVariable:'abc123' };
});

/ / ctrl:

myApp.controller('MyCtrl', function($scope, myService) {

  $scope.someVariable = myService.someVariable;

  // watch the service and update this ctrl...
  $scope.$watch(function(){
    return myService.someVariable;
  }, function(newValue){
    $scope.someVariable = newValue;
  });
});

你可以在$rootScope中插入服务,然后观察:

myApp.run(function($rootScope, aService){
    $rootScope.aService = aService;
    $rootScope.$watch('aService', function(){
        alert('Watch');
    }, true);
});

在你的控制器中:

myApp.controller('main', function($scope){
    $scope.aService.foo = 'change';
});

另一个选择是使用外部库,例如:https://github.com/melanke/Watch.JS

"发射架:IE +, f4 +,稳定基金5+

您可以观察一个、多个或所有对象属性的变化。

例子:

var ex3 = {
    attr1: 0,
    attr2: "initial value of attr2",
    attr3: ["a", 3, null]
};   
watch(ex3, function(){
    alert("some attribute of ex3 changes!");
});
ex3.attr3.push("new value");​

我迟到了,但我找到了一个比上面的答案更好的方法。我没有分配一个变量来保存服务变量的值,而是创建了一个附加到作用域的函数,该函数返回服务变量。

控制器

$scope.foo = function(){
 return aService.foo;
}

我觉得这能满足你的要求。我的控制器通过这个实现不断检查我的服务的值。老实说,这比选择的答案要简单得多。

我在另一个线程上找到了一个非常好的解决方案,有类似的问题,但方法完全不同。当$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和给定的更改-我分别做出反应。非常简单和优雅!