角。看服务变化?

时间:2014-11-08 00:57:14

标签: angularjs data-binding binding

您有一个名为“ 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不起作用。

1 个答案:

答案 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.equalsangular.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