我在使用Angular.js时遇到了一个问题。
我试图建立一个简单的发票web应用程序…
在编辑发票时,用户应该能够插入和删除新项目。
每个项目都有一个只读字段,该字段是小计(unit price * qty)
,由函数calcSubTotal(row)
在发票的最后,有一个GrandTotal,由函数calcGrandTotal()
,
HTML:<div data-ng-repeat='row in rows'>
Unit Price: <input type='text' name='price' data-ng-model='row.unit_price' />
Qty: <input type='text' name='qty' data-ng-model='row.qty' />
<input type='text' readonly value='{{ calcSubTotal(row) }}' />
</div>
<p>GRAND TOTAL: {{ calcGrandTotal() }}</p>
JS (编辑):
$scope.calcSubTotal = function(row) {
console.log(row);
return (row.unit_price * row.qty);
}
$scope.calcGrandTotal = function() {
var total = 0.00;
$($scope.rows).each(function(i, row) {
var x = $scope.calcSubTotal(row);
total += x || 0.00;
});
return total;
};
现在,如果我将console.log("CALLED")
放入calcGrandTotal()
函数中,我看到它被调用了很多次。
编辑:
最糟糕的是,如果我将console.log(行)放在calcSubTotal(行)函数中,我可以看到,即使在修改发票中的单个项目时,也会对所有项目调用该函数。
我的意思是,如果我修改了第1项,它不应该重新计算第2项,而应该只更新总额(基于先前计算的第2项的小计,它没有改变…)
我如何优化这个东西?
谢谢。
将函数放在ngBind
括号内的问题是,它每次渲染视图时都会调用。只有当每一行的数量或价格发生变化时,才应该计算总数。考虑这个
EDIT:我没看到你在计算每行项目的小计。下面是修改后的解决方案:
<div ng-repeat="row in rows">
<input ng-model="row.qty" ng-change="calculateTotals()"/>
<input ng-model="row.price" ng-change="calculateTotals()"/>
<input readonly value="{{row.subTotal}}"/>
</div>
<div ng-bind="grandTotal"></div>
然后在你的控制器/指令中做这样的事情
$scope.calculateTotals = function() {
var grandTotal = 0;
angular.forEach($scope.rows, function(row) {
row.subTotal = row.qty * row.price;
grandTotal += row.subTotal;
});
$scope.grandTotal = grandTotal;
}
注意:您可能还必须在接收到行数据后在控制器的某个地方调用它:
$http.get('/my/invoice/').success(function(rows){
$scope.rows = rows;
$scope.calculateTotals();
});
您可能想要这样做,
HTML(和你的一样)
<div data-ng-repeat='row in rows'>
<p>row {{$index}}</p>
Unit Price: <input type='text' name='price' data-ng-model='row.unit_price' />
<br>
Qty: <input type='text' name='qty' data-ng-model='row.qty' />
<br>
<input type='text' readonly value='{{ calcSubTotal(row) }}'>
</div>
<p>GRAND TOTAL: {{ calcGrandTotal() }}</p>
JS
angular.module("app", []).controller('ctrl', function($scope){
$scope.rows = [{unit_price: 0, qty: 0}, {unit_price: 0, qty: 0}];
$scope.calcSubTotal = function(row){
return parseFloat(row.unit_price) * parseFloat(row.qty);
}
$scope.calcGrandTotal = function() {
var total = 0.00;
$($scope.rows).each(function(i, row) {
var x = $scope.calcSubTotal(row);
total += x || 0.00;
});
return total;
};
});
我把这些放在一起了