javascript Angular.js 只观察特定的对象属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15522015/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 01:04:54  来源:igfitidea点击:

Angular.js watch only on particular object property

javascriptobjectangularjswatchangularjs-scope

提问by fxck

Basically I want this http://plnkr.co/edit/3yfXbo1c0llO40HZ8WNP?p=previewbut watch doesn't fire when I change something..

基本上我想要这个http://plnkr.co/edit/3yfXbo1c0llO40HZ8WNP?p=preview但是当我改变一些东西时手表不会触发..

I know that this would have worked

我知道这会奏效

$scope.$watch('stuff', function (newVal, oldVal) {
    console.log(oldVal, newVal);

}, true);

But since I want to do some summing up inside the watches and I don't want to unnecessarily loop thru or re-sum values that did not change..

但是因为我想在手表内部做一些总结,我不想不必要地循环或重新总结没有改变的值..

//edit - note that the plnkr example is just an extraction from the actual app, where you can add and remove rows and much more, like modifying the total number(sum of somethings and somethingelses) from another input outside the ng-repeat..

//edit - 请注意,plnkr 示例只是从实际应用程序中提取的内容,您可以在其中添加和删除行等等,例如修改来自 ng-repeat 之外的另一个输入的总数(某物和某物的总和)。 .

回答by Mathew Berg

I would not do a watch as depending on how large your array could be, might be very taxing. Instead I would just create a filter:

我不会做手表,因为这取决于您的阵列有多大,可能会非常费力。相反,我只想创建一个过滤器:

HTML:

HTML:

Sum of something is: {{ stuff | sum:'something' }}<br/>
Sum of somethingelse is: {{ stuff | sum:'somethingelse' }}

Javascript:

Javascript:

.filter("sum", function(){
    return function(input, params){
        var totalSum = 0;
        for(var x = 0; x < input.length; x++){
            totalSum += input[x][params];
        }
        return totalSum;
    }
})

plnkr: http://plnkr.co/edit/p6kM3ampSuMXnwqcteYd?p=preview

plnkr:http://plnkr.co/edit/p6kM3ampSuMXnwqcteYd?p=preview

回答by ganaraj

I am smiling all over the place after I came up with this solution for your problem. Not only is this solution going to watch individual objects, it also is not going to do a complete loop through the rest of the objects for the summation.

在我为您的问题想出这个解决方案后,我满脸笑容。此解决方案不仅要查看单个对象,而且不会对其余对象进行完整循环以求和。

http://plnkr.co/edit/oPWobcLLtJlxs5vjTYyc?p=preview

http://plnkr.co/edit/oPWobcLLtJlxs5vjTYyc?p=preview

app.controller('MainCtrl', function($scope) {
  $scope.stuff = STUFF;
  var i;
  $scope.sumOfSomething = 0;
  $scope.sumOfSomethingElse = 0;

  for(i=0;i < $scope.stuff.length;i++ ){
    $scope.$watch('stuff['+i+'].something', function (newVal,oldVal) {
      // happens when the watch is registered.
      if(oldVal === newVal){
        $scope.sumOfSomething += +newVal;
        return;
      }
      if(newVal){
        $scope.sumOfSomething += + (newVal - oldVal);
      }
    });

    $scope.$watch('stuff['+i+'].somethingelse', function (newVal,oldVal) {
      // happens when the watch is registered. 
      if(oldVal === newVal){
        $scope.sumOfSomethingElse += +newVal;
        return;
      }

      if(newVal){
        $scope.sumOfSomethingElse += + (newVal - oldVal);
      }

    });  
  }
});

By the way I dont know how optimal this solution is going to be if you have a large number of objects in STUFF. Also, this wont work as is if the number of objects in STUFFis going to change. What we are basically doing is using the dirty checking loop of angular to do our summation for us.

顺便说一句,如果您在STUFF. 此外,如果对象的数量STUFF将发生变化,这将无法正常工作。我们基本上做的是使用 angular 的脏检查循环来为我们做求和。

Also notice the order of newVal and oldVal in the watch listener. Your order is wrong.

还要注意 watch 监听器中 newVal 和 oldVal 的顺序。你的顺序错了。

回答by cirrus

Since $watch()takes an angular expression you can use a custom watcher function. In your case the easiest way to watch for changes is simply to add up all the fields you're interested in then return a single number which is nice and efficient for angular and your sum will be ready to render.

由于$watch()采用角度表达式,因此您可以使用自定义观察器函数。在您的情况下,最简单的观察变化的方法是简单地将您感兴趣的所有字段相加,然后返回一个对角度来说很好且有效的数字,并且您的总和将准备好呈现。

var sumThings = function(obj, field) {
  var val = 0;
  obj.forEach(function(o) {
    val += parseInt(o[field]);
  });
  return val;
};

$scope.$watch(function() { return sumThings($scope.stuff, "something")}, function (newVal, oldVal) {    //console.log("watchExpression('something') fired!", oldVal, newVal);
  $scope.somethingSum = newVal;
});

$scope.$watch(function() { return sumThings($scope.stuff, "somethingelse")}, function (newVal, oldVal) {
  $scope.somethingelseSum = newVal;
});

Basically, by doing your summation you're doing your own dirty checking. It'll be more efficient than $watch(STUFF, true)if your objects are more complex than you've shown here.

基本上,通过进行求和,您就是在进行自己的脏检查。$watch(STUFF, true)如果您的对象比您在此处显示的更复杂,它会更有效。

Your updated plnkr : http://plnkr.co/edit/d7CvERu3XGkub4l6f1yw?p=preview

您更新的 plnkr :http://plnkr.co/edit/d7CvERu3XGkub4l6f1yw?p=preview

回答by Caio Cunha

Well, if I got it, you just want to sum somethingwith somethingelseof the inner objects when they change. And you don't want to loop through all the other inner objects if the change is in one of them.

好吧,如果我得到了它,你只是想总结somethingsomethingelse内部的物体时,他们改变。如果更改发生在其中一个对象中,则您不想遍历所有其他内部对象。

Well, your $watchisn't firing for there is no stuff.property, and there is no patterns like stuff.*.something.

好吧,您$watch不会因为没有stuff.property,也没有像stuff.*.something.

If you know the moment the objects gets pushed or pulled from the array, than you can apply a separately $scope.$watch(object, function(){}, true)before/after inserting each one to the array. If you don't know this moment, than you will need to $watchthe entire array, and when a change happens, run all deregistration functions and $watchthem all again, one by one.

如果您知道对象从数组中被推入或拉出的那一刻,那么您可以$scope.$watch(object, function(){}, true)在将每个对象插入数组之前/之后单独应用。如果您不知道这一刻,那么您将需要$watch整个数组,并且当发生更改时,请运行所有注销功能,$watch然后再一次运行它们。

Anyway, a loop in nowadays browsers is pretty fast, and except you're doing heavy calculations and you have millions of objects (what would have been a memory problem already) you'll probably be good with it. So, an effort to $watchthem all separately is only necessary if you have really heavy calculations, that could comprise the system performance.

无论如何,当今浏览器中的循环非常快,除非您进行大量计算并且您有数百万个对象(这本来是内存问题),否则您可能会很好地使用它。因此,$watch只有在您有非常繁重的计算时才需要分别对它们进行处理,这可能会影响系统性能。