问题描述
在学习用angular做购物车功能时,遇到一个问题:我在删除一条商品时,总价没有跟着变动,折腾了几天,实在琢磨不出,请大家帮忙看看,谢谢大家了
<!doctype html><html ng-app='todoApp'><head> <meta charset='utf-8'/> <title>To Do List</title> <link rel='stylesheet' href='https://www.6hehe.com/wenda/css/bootstrap.min.css'> <script src='https://www.6hehe.com/wenda/js/angular.js'></script> <script src='https://www.6hehe.com/wenda/js/jquery-1.11.1.js'></script> <script>var model2 = [ {name:'shoes',id:1,price:22,total:2}, {name:'T-shirt',id:1,price:12,total:2}, {name:'dress',id:1,price:25,total:2},]var todoApp = angular.module('todoApp',[]);todoApp.controller('ToDoCtrl',function($scope){ $scope.todo2 = model2; $scope.init = function(){$scope.allchecked(); } $scope.checkedone= function(){var totals = 0;for(var i=0; i<$scope.todo2.length;i++){ if($scope.todo2[i].status == true){$scope.allstatus = truetotals += $scope.todo2[i].price * $scope.todo2[i].total; }else{$scope.allstatus = false }}$('.total').text(totals)alert($scope.todo2.length) } $scope.allchecked= function(ev){var totals = 0;var selected = 0;$scope.allstatus =true;for(var i=0; i<$scope.todo2.length;i++){ if($scope.allstatus ==true){$scope.todo2[i].status = true;totals += $scope.todo2[i].price * $scope.todo2[i].total;//selected += }else{$scope.todo2[i].status = false; }}$('.total').text(totals) } $scope.del= function(id){alert( $scope.todo2.length)$scope.todo2.splice(id,1) }}) </script> <style>table tr td{border:1px #ccc solid; padding:10px} </style></head><body ng-controller='ToDoCtrl' ng-init='init()'> <table><tr> <td> <input type='checkbox' ng-model='allstatus' ng-change='allchecked(allstatus)'/></td> <td>name</td><td>price</td><td>total</td><td><span class='total'></span></td><td>del</td></tr><tr ng-repeat='z in todo2'> <td> <input type='checkbox' ng-model='z.status' ng-change='checkedone()'/></td> <td>{{z.name}}</td> <td>{{z.total}}</td> <td>{{z.price}}</td> <td>{{z.total * z.price}}</td> <td><span ng-click='del(z.id)'>delted</span></td></tr> </table></body></html>
问题解答
回答1:添加一个函数
function totalPrize(){ var total=0; angular.forEach($scope.todo2,function(item,index){total+=item.price*item.total; }) $(’.total’).text(total);}
并且del函数改为
$scope.del = function(id) {//alert($scope.todo2.length)$scope.todo2.splice(id,1)totalPrize(); }
我必须吐槽下是,你现在的代码根本不像在用angular写东西啊,还是停留在jQuery的层面上。 减少dom操作是Angularjs的初衷,但是你直接用.text()方法给赋值。为什么不直接把total绑定在$scope上,在html上直接{{total}}就可以了啊。另外,将数组model2直接放在外面,污染全局变量不可取。也可以将初始化init的代码放在controller中,没必要在html中init。
删除数组中的元素,总价没有理由跟着变化,一则总价没绑定到scope上,再则即使总价这个变量绑定到scope上,也是原始数据类型,你每次操作后,要获得总价都是要再算一次的。
<!doctype html><html ng-app='todoApp'> <head><meta charset='utf-8' /><title>To Do List</title><link rel='stylesheet' href='https://www.6hehe.com/bootstrap/css/bootstrap.min.css'><style> table tr td {border: 1px #ccc solid;padding: 10px }</style> </head> <body ng-controller='ToDoCtrl'><table> <tr><td> <input type='checkbox' ng-model='allstatus' ng-change='allchecked()' /></td><td>name</td><td>price</td><td>total</td><td>{{total}}</td><td>del</td> </tr> <tr ng-repeat='z in todo2'><td> <input type='checkbox' ng-model='z.status' ng-change='checkedone($event)' /></td><td>{{z.name}}</td><td>{{z.total}}</td><td>{{z.price}}</td><td>{{z.total * z.price}}</td><td><span ng-click='del(z.id)'>delted</span></td> </tr></table><script src='https://www.6hehe.com/wenda/angular.min.js'></script><script src='https://www.6hehe.com/jquery.js'></script><script> var todoApp = angular.module('todoApp', []); todoApp.controller('ToDoCtrl', function($scope) {var model2 = [{ name: 'shoes', id: 1, price: 22, total: 2}, { name: 'T-shirt', id: 1, price: 12, total: 2}, { name: 'dress', id: 1, price: 25, total: 2}];$scope.todo2 = model2;$scope.total=0;function init() { $scope.allstatus=true; angular.forEach($scope.todo2,function(item){item.status=true;$scope.total+=item.price*item.total }) }init();$scope.checkedone = function() { totalPrize();$scope.allstatus=checkAll();}function checkAll(){ for(var i=0;i<$scope.todo2.length;i++){if(!$scope.todo2[i].status){ return false;}} return true;}$scope.allchecked=function(){ if($scope.allstatus){for(var i=0;i<$scope.todo2.length;i++){ $scope.todo2[i].status=true;} }else{for(var i=0;i<$scope.todo2.length;i++){ $scope.todo2[i].status=false;} } totalPrize()}$scope.del = function(id) { $scope.todo2.splice(id,1) totalPrize();}function totalPrize(){ $scope.total=0; angular.forEach($scope.todo2,function(item,index){if(item.status){ $scope.total+=item.price*item.total;} }) } })</script> </body></html>
插一段我的代码,还有好多可以优化的,但是我要去跑步啦,没时间改啦。 要用的话,注意引入js,css文件的路径
回答2:如果你直接使用jQuery来修改VIEW层或者MODEL层数据,那你需要手动进行数据同步。你可以根据需要使用:
$scope.$digest()
或者
$scope.$apply(function(){ //do sth here.})
来同步数据。具体可以参考AngularJS的API