角度$watch不起作用

Angular $watch not working

本文关键字:不起作用 watch 角度      更新时间:2023-09-26

我在控制器上使用两个$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"]
};

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

问题是,我想创建另一个图表,

该图表读取另一个等于这些的对象,但用此方法计算它的数据:

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图表不起作用,这些手表也不起作用。

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

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

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

  2. 您可以通过将objectEquality标志设置为 true ( $scope.$watch('x', function(){}, true) 来绕过 1.然后,这将进行深入比较,并应发现data数组中的差异。但是,这需要更多的性能。

由于您只是在每个对象中使用data数组,因此您可以简单地在gastos.data上使用$scope.$watchCollection。这更干净、更快。

下面是一个演示这一点的工作片段:

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;
  }
})
<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>

使用$watchCollection而不是$watch来监视集合。

或者你也可以这样看:

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