javascript 在 AngularJS 重复部分中多次调用函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14987277/
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
Function Called Multiple Times in AngularJS Repeat Section
提问by Dan Wahlin
I'm running into an issue where I want to bind to the output of a function inside of an ng-repeat loop. I'm finding that the function is being called twice per item rather than once as I'd expect. Here's the ng-repeat section (notice the calcRowTotal() call at the end):
我遇到了一个问题,我想绑定到 ng-repeat 循环内的函数的输出。我发现每个项目都调用了该函数两次,而不是像我期望的那样调用一次。这是 ng-repeat 部分(注意最后的 calcRowTotal() 调用):
<tr ng-repeat="row in timesheetRows">
<td>
<select ng-model="row.categoryID">
<option ng-repeat="category in categories" value="{{category.id}}">
{{category.title}}
</option>
</select>
</td>
<td ng-repeat="day in row.dayValues">
<input type="text" ng-model="day.hours" />
</td>
<td>{{calcRowTotal($index, row)}}</td>
</tr>
The calcRowTotal() function is shown next:
calcRowTotal() 函数如下所示:
$scope.calcRowTotal = function (index, row) {
console.log('calcRowTotal - Index: ' + index);
var total = 0;
for (var i = 0; i < row.dayValues.length; i++) {
var num = parseFloat(row.dayValues[i].hours);
if (isNaN(num)) {
num = 0;
//this.dayValues[i].hours = 0;
}
total += num;
}
//updateDayTotals();
return total;
}
An example of one of the items being iterated through is shown next:
下面显示了正在迭代的项目之一的示例:
{
categoryID: 2,
dayValues: [
{ day: $scope.days[0], hours: 5 },
{ day: $scope.days[1], hours: 0 },
{ day: $scope.days[2], hours: 3 },
{ day: $scope.days[3], hours: 0 },
{ day: $scope.days[4], hours: 2 },
{ day: $scope.days[5], hours: 5 },
{ day: $scope.days[6], hours: 8 }
]
}
I'm seeing the following in the console (two items are currently in the collection I'm looping through):
我在控制台中看到以下内容(我正在循环的集合中目前有两个项目):
calcRowTotal - Index: 0
calcRowTotal - Index: 1
calcRowTotal - Index: 0
calcRowTotal - Index: 1
I could certainly make a "rowTotal" property but would prefer to bind to "live" data provided by the function shown above. Hopefully the duplication is something simple I'm missing so I appreciate any feedback on why I'm seeing the duplication. As a side note, as data in one of the textboxes changes I need to update the row totals as well so it may be I need a different approach. Interested in understanding this particular situation first though....definitely don't want the duplication because there could be a lot of rows potentially.
我当然可以创建一个“rowTotal”属性,但更愿意绑定到上面显示的函数提供的“实时”数据。希望重复是我遗漏的一些简单的东西,所以我感谢任何关于为什么我看到重复的反馈。作为旁注,随着其中一个文本框中的数据发生变化,我也需要更新行总数,因此我可能需要一种不同的方法。有兴趣首先了解这种特殊情况....绝对不想要重复,因为可能有很多行。
Here's an example: http://jsfiddle.net/dwahlin/Y7XbY/2/
这是一个例子:http: //jsfiddle.net/dwahlin/Y7XbY/2/
回答by Ben Lesh
It's because you're binding to a function expression here:
这是因为您在这里绑定了一个函数表达式:
<td>{{calcRowTotal($index, row)}}</td>
What that does it force that function to be reevaluated on every item, on every digest. What you'll want to do to prevent that is pre-calculate that value and put it in your array to begin with.
它是什么迫使在每个项目、每个摘要上重新评估该功能。您需要做的是预先计算该值并将其放入数组中以防止出现这种情况。
One way to do that is to set up a watch on your array:
一种方法是在您的阵列上设置一个手表:
$scope.$watch('timesheetRows', function(rows) {
for(var i = 0; i < value.length; i++) {
var row = rows[i];
row.rowTotal = $scope.calcRowTotal(row, i);
}
}, true);
Then all you have to do is bind to that new value:
然后你所要做的就是绑定到这个新值:
<td>{{row.rowTotal}}</td>
回答by saurabh
Its totally because you're binding to a function expression as @Ben Lesh suggested. Somehow using $watch also got me executing the same function twice. Solution to refrain from double execution that we used is by using ng-init for function call. Simply create an init variable with function return as value and use that in ur expression as below:
这完全是因为您绑定到了@Ben Lesh 建议的函数表达式。不知何故,使用 $watch 也让我执行了两次相同的功能。我们使用的避免双重执行的解决方案是使用 ng-init 进行函数调用。只需创建一个带有函数返回值的 init 变量,然后在你的表达式中使用它,如下所示:
<tr ng-repeat="row in timesheetRows" ng-init="rowTotalValue=calcRowTotal($index, row)">
<td>
<select ng-model="row.categoryID">
<option ng-repeat="category in categories" value="{{category.id}}">
{{category.title}}
</option>
</select>
</td>
<td ng-repeat="day in row.dayValues">
<input type="text" ng-model="day.hours" />
</td>
<td>{{rowTotalValue}}</td>
This worked for me where I was passing a single attribute of row. Not tried with $index though. But I assume it should work.
这对我有用,我正在传递行的单个属性。虽然没有尝试过 $index 。但我认为它应该有效。
回答by Christopher Marshall
I actually had a similar problem recently.
我最近实际上遇到了类似的问题。
Ended up iterating through each sub-object and binding the totals to a model. Shouldn't be an issue, especially if you're only using the total for display purposes.
最终遍历每个子对象并将总数绑定到模型。应该不是问题,特别是如果您仅将总数用于显示目的。
eg.
例如。
// Reset to Zero
$scope.rowTotal = 0;
jquery.each($scope.row, function(key, value) {
$scope.totalRow += value.hours;
});
and iterate through each row.
并遍历每一行。