Angular $ watch无效

时间:2016-02-25 09:34:32

标签: javascript angularjs

我在我的控制器上使用了两个$watches,它们应该关注这两个对象:

$scope.gastos = {
    name: "Gastos mensuales",
    data: [0,0,0,0,0,0,0,0,0,0,0,0],
    labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo",
                "Junio", "Julio", "Agosto", "Septiembre", "Octubre",
                "Noviembre", "Diciembre"]
};

$scope.ganancias = {
    name: "Ganancias mensuales",
    data: [0,0,0,0,0,0,0,0,0,0,0,0],
    labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo",
                "Junio", "Julio", "Agosto", "Septiembre", "Octubre",
                "Noviembre", "Diciembre"]
};

两个图表(来自Charts.js和angular-charts插件)从中读取数据。我已经将图表放在从属性接收数据的自定义指令中,并且它们正常工作。

问题是,我想创建另一个图表来读取与这些对象相同的另一个对象,但是在这个方法中计算它的数据:

function calcularBeneficios(){
 var data = [];
 for(var i=0;i<12;i++){
    data[i] = $scope.ganancias.data[i] - $scope.gastos.data[i];
 }
    console.log("FUNCTION DATA: "+data);
 return data;
}

这些是手表(我试过看objectobject.data变量):

$scope.$watch("gastos", function(){
  $scope.beneficios.data = calcularBeneficios();
  console.log("SCOPE: "+$scope.beneficios.data);
});

$scope.$watch("ganancias", function(){
  $scope.beneficios.data = calcularBeneficios();
  console.log("SCOPE: "+$scope.beneficios.data);
});

这不起作用。你看到所有的console.logs?我只看到"SCOPE" console.log一次(ganancias甚至不见两次)。当我更改绑定到这两个对象的某些输入中的数据时,一切正常(图表得到实时更新),但beneficios图表没有,这些手表也没有工作。

我在这两块手表上做错了吗?

2 个答案:

答案 0 :(得分:5)

问题是您正在观看顶级gastosganancias对象。这有两个潜在的问题:

  1. 正如docs for $watch所说,默认情况下,正常的JavaScript不等式用于确定对象是否已更改(x !== y)。由于对象本身是同一个对象,您只是在中更改数据,这将始终为真,因此$watch不会被触发。

  2. 您可以通过将objectEquality标志设置为true($scope.$watch('x', function(){}, true))来解决问题。然后进行深入比较,并在data数组中找出差异。然而,这更加注重性能。

  3. 由于您只是在每个对象中使用data数组,因此您只需在gastos.data上使用$scope.$watchCollection即可。这更清洁,更快。

    这是一个展示这个的工作片段:

    &#13;
    &#13;
    angular.module("myApp", []).controller('myCtrl', function($scope) {
    
      // same code
      function calcularBeneficios() {
        var data = [];
        for (var i = 0; i < 12; i++) {
          data[i] = $scope.ganancias.data[i] - $scope.gastos.data[i];
        }
        console.log("FUNCTION DATA: " + data);
        return data;
      }
    
      
      $scope.beneficios = {
        name: "Beneficios mensuales",
        data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo",
          "Junio", "Julio", "Agosto", "Septiembre", "Octubre",
          "Noviembre", "Diciembre"
        ]
      };
      
      $scope.gastos = {
        name: "Gastos mensuales",
        data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo",
          "Junio", "Julio", "Agosto", "Septiembre", "Octubre",
          "Noviembre", "Diciembre"
        ]
      };
    
      $scope.ganancias = {
        name: "Ganancias mensuales",
        data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo",
          "Junio", "Julio", "Agosto", "Septiembre", "Octubre",
          "Noviembre", "Diciembre"
        ]
      };
    
      // watch the array collection in gastos.data 
      $scope.$watchCollection("gastos.data", function() {
        $scope.beneficios.data = calcularBeneficios();
        console.log("SCOPE: " + $scope.beneficios.data);
      });
    
      // watch the array collection in ganancias.data 
      $scope.$watchCollection("ganancias.data", function() {
        $scope.beneficios.data = calcularBeneficios();
        console.log("SCOPE: " + $scope.beneficios.data);
      });
      
      
      // testing functions
    
      $scope.changeGastos = function() {
        $scope.gastos.data[4] = 10;
      }
      
      $scope.changeGanancias = function() {
        $scope.ganancias.data[0] = 40;
      }
    })
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
    
    <div ng-app="myApp" ng-controller="myCtrl">
      <h3>beneficios.data</h3>
      <ul>
        <li ng-repeat="i in beneficios.data track by $index">{{i}}</li>
      </ul>
      <button ng-click="changeGastos()">Change Gastos</button>
      <button ng-click="changeGanancias()">Change Ganancias</button>
    </div>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:3)

使用$watchCollection代替$watch来观看收藏。

或者你也可以这样看:

$scope.$watch("gastos + ganancias", function(){
  $scope.beneficios.data = calcularBeneficios();
  console.log("SCOPE: "+$scope.beneficios.data);
});