简体   繁体   English

Angular.js仅监视特定的对象属性

[英]Angular.js watch only on particular object property

Basically I want this http://plnkr.co/edit/3yfXbo1c0llO40HZ8WNP?p=preview but 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.. //编辑 - 请注意,plnkr示例只是从实际应用程序中提取,您可以在其中添加和删除行等等,例如从ng-repeat之外的另一个输入修改总数(某些事物和某些事物的总和)。 。

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

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 . 顺便说一句,如果你在STUFF有大量的对象,我不知道这个解决方案会有多优化。 Also, this wont work as is if the number of objects in STUFF is going to change. 此外,如果STUFF的对象数量将发生变化,这将不会起作用。 What we are basically doing is using the dirty checking loop of angular to do our summation for us. 我们基本上做的是使用角度的脏检查循环来为我们做总结。

Also notice the order of newVal and oldVal in the watch listener. 还要注意watch监听器中newVal和oldVal的顺序。 Your order is wrong. 你的订单错了。

Since $watch() takes an angular expression you can use a custom watcher function. 由于$watch()采用角度表达式,因此您可以使用自定义观察器功能。 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. 在您的情况下,观察更改的最简单方法是简单地将您感兴趣的所有字段相加,然后返回单个数字,这对于角度来说是好的和有效的,并且您的总和将准备好呈现。

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)它将比$watch(STUFF, true)更有效。

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

Well, if I got it, you just want to sum something with somethingelse of the inner objects when they change. 好吧,如果我得到了它,你只是想总结somethingsomethingelse当他们改变内部对象。 And you don't want to loop through all the other inner objects if the change is in one of them. 并且如果更改位于其中一个内部对象中,则不希望循环遍历所有其他内部对象。

Well, your $watch isn't firing for there is no stuff.property , and there is no patterns like stuff.*.something . 好吧,你的$watch没有因为没有stuff.property而被stuff.property ,并且没有类似stuff.*.something模式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. 如果您知道从数组中推送或拉出对象的时刻,那么您可以在将每个$scope.$watch(object, function(){}, true)插入数组之前/之后应用单独的$scope.$watch(object, function(){}, true) If you don't know this moment, than you will need to $watch the entire array, and when a change happens, run all deregistration functions and $watch them all again, one by one. 如果您不知道这一刻,那么您将需要$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 $watch them all separately is only necessary if you have really heavy calculations, that could comprise the system performance. 因此,只有在您进行了非常繁重的计算(包括系统性能)时才需要单独$watch它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM