vue.js實戰第5章 54頁的練習1
直接放代碼好了,全選的部分搞了好久,代碼好像有點啰嗦,好在實現功能了(*^▽^*)
HTML:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>購物車示例</title> <link rel="stylesheet" href="index.css"> </head> <body> <div id="app" v-cloak> <template v-if="list.length"> <table> <thead> <tr> <th> <input type="checkbox" v-model="checkAll">全選 </th> <th>商品名稱</th> <th>商品單價</th> <th>購買數量</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="(item,index) in list"> <!-- <td>{{index+1}}</td> --> <td><input type="checkbox" :checked="item.check" @click="isAll(index)"> {{item.check}}</td> <td>{{item.name}}</td> <td>{{item.price}}</td> <td> <button @click="handleReduce(index)" :display="item.count===1">-</button> {{item.count}} <button @click="handleAdd(index)">+</button> </td> <td> <button @click="handleRemove(index)">移除</button> </td> </tr> </tbody> </table> <div>總價:¥{{totalPrice}}</div> </template> <div v-else> 購物車為空 </div> </div> <script src="../vue.js"></script> <script src="index.js"></script> </body> </html>
JS:
var app=new Vue({ el:'#app', data:{ list:[ { id:1, name:'iPhone 7', price:6288, count:1, check:false },{ id:2, name:'iPad Pro', price:5888, count:1, check:false },{ id:3, name:'MacBook Pro', price:21488, count:1, check:false } ], checkAll:false, smallHand:false }, computed:{ totalPrice:function(){ this.newList=this.list.filter(function(item){ if(item.check){ return item; } }); var total=0; for(var i=0;i<this.newList.length;i++){ var item=this.newList[i]; total+=item.price*item.count; } return total.toString().replace(/\B(?=(\d{3})+$)/g,',');//匹配后面已3個數字結尾的非單詞邊界,換成“,” /* replace: 用於在字符串中用一些字符替換另一些字符,或替換一個與正則表達式匹配的子串 \B :匹配非單詞邊界 (red|blue|green):查找任何指定的選項 ?=n :匹配任何其后緊接指定字符串n的字符串(n量詞) 提供后面的n找? \d :查找數字 n{X}:匹配包含X個n的序列字符串 \d{3}:匹配含有3個數字的字符串 n$ :匹配任何結尾為n的字符串 n+ :匹配任何包含至少一個n的字符串 (\d{3})+$ :匹配至少一個已含有3個數字字符串結尾的字符 */ } }, methods:{ handleReduce:function(index){ if(this.list[index].count===1) return; this.list[index].count--; }, handleAdd:function(index){ this.list[index].count++; }, handleRemove:function(index){ this.list.splice(index,1); }, isAll:function(index){ console.log(this.list[index].check); var indexItem=this.list[index]; indexItem.check=!indexItem.check; var num=0; for(var i=0;i<this.list.length;i++){ var item=this.list[i]; if(item.check){ num++; }else{ num--; } } console.log(num);////(選中了最后一個)3-全部勾選-勾選全選 (之前全部勾選,取消了任意一個勾選) 1-取消全選的勾選 if(num==3||(num==1&&indexItem.check==false)){ //考慮不周全 this.checkAll=indexItem.check; this.smallHand=true; } } }, watch:{ checkAll:function(){ if(this.smallHand){ }else{ for(var i=0;i<this.list.length;i++){ this.list[i]['check']=this.checkAll; } } this.smallHand=false; } } })
JS部分補充說明:上面的代碼在刪除時沒辦法繼續“全選”的同步,而且這里數字被寫死是錯誤的( if(num==3||(num==1&&indexItem.check==false)){ )。
更新改進后的代碼如下:
var app=new Vue({ el:'#app', data:{ list:[ { id:1, name:'iPhone 7', price:6288, count:1, check:false },{ id:2, name:'iPad Pro', price:5888, count:1, check:false },{ id:3, name:'MacBook Pro', price:21488, count:1, check:false } ], checkAll:false, smallHand:false }, computed:{ totalPrice:function(){ this.newList=this.list.filter(function(item){ if(item.check){ return item; } }); var total=0; for(var i=0;i<this.newList.length;i++){ var item=this.newList[i]; total+=item.price*item.count; } return total.toString().replace(/\B(?=(\d{3})+$)/g,',');//匹配后面已3個數字結尾的非單詞邊界,換成“,” /* replace: 用於在字符串中用一些字符替換另一些字符,或替換一個與正則表達式匹配的子串 \B :匹配非單詞邊界 (red|blue|green):查找任何指定的選項 ?=n :匹配任何其后緊接指定字符串n的字符串(n量詞) 提供后面的n找? \d :查找數字 n{X}:匹配包含X個n的序列字符串 \d{3}:匹配含有3個數字的字符串 n$ :匹配任何結尾為n的字符串 n+ :匹配任何包含至少一個n的字符串 (\d{3})+$ :匹配至少一個已含有3個數字字符串結尾的字符 */ } }, methods:{ handleReduce:function(index){ if(this.list[index].count===1) return; this.list[index].count--; }, handleAdd:function(index){ this.list[index].count++; }, handleRemove:function(index){ this.list.splice(index,1); var num=0; var allNum=0; for(var i=0;i<this.list.length;i++){ var item=this.list[i]; allNum++; if(item.check){ num++; }else{ num--; } } if(num==allNum){ this.checkAll=true; }else{ this.checkAll=false; } }, isAll:function(index){ console.log(this.list[index].check); var indexItem=this.list[index]; indexItem.check=!indexItem.check; var num=0; var allNum=0; for(var i=0;i<this.list.length;i++){ var item=this.list[i]; allNum++; if(item.check){ num++; }else{ num--; } } console.log(num);////(選中了最后一個)3-全部勾選-勾選全選 (之前全部勾選,取消了任意一個勾選) 1-取消全選的勾選 // if(num==3||(num==1&&indexItem.check==false)){ 這里不能寫死的傻瓜 if(num==allNum||(num==(allNum-2)&&indexItem.check==false)){ this.checkAll=indexItem.check; this.smallHand=true; } } }, watch:{ checkAll:function(){ if(this.smallHand){ }else{ for(var i=0;i<this.list.length;i++){ this.list[i]['check']=this.checkAll; } } this.smallHand=false; } } })
css:
[v-cloak] { display: none; } table { border: 1px solid #e9e9e9; border-collapse: collapse; border-spacing: 0; empty-cells: show; } table th, table td { padding: 8px 16px; border: 1px solid #e9e9e9; text-align: left; } table th { background: #f7f7f7; color: #5c6b77; font-weight: 600; white-space: nowrap; }