实现需求:
实现一个简易的购物车,页面的表格展示data数据中的一个数组对象,并提供选中商品和全选商品checkbox复选框,页面实时显示选中商品的总金额:
分析:
1:使用v-for循环渲染arraylist对象;
2:使用computed计算属性计算总价;
3:使用computed计算全选复选框是否应该被选中(商品列表如果都被勾选,则设置全选复选框的状态为选中,否则设置全选复选框状态为取消选中);
4:根据数组中元素的初始选中状态,设置页面商品复选框是否选中。
代码实现:
使用html文件作为页面显示,引入js文件,Vue代码写在index.js中,页面样式保存在style.css中。
HTML:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset=utf-8> 5 <title>Test page</title> 6 <link rel="stylesheet" type="text/css" href="style.css"> 7 </head> 8 <body> 9 <div id="app" v-cloak> 10 <template v-if='list.length'> 11 <table> 12 <thead> 13 <tr> 14 <th> 15 <input type="checkbox" v-model="checkAll" :checked="checkAll" @change="handleCheckAll">选择 16 </th> 17 <th></th> 18 <th>商品名称</th> 19 <th>商品单价</th> 20 <th>购买数量</th> 21 <th>操作</th> 22 </tr> 23 </thead> 24 <tbody> 25 <tr v-for='(item, index) in list'> 26 <td> 27 <input type="checkbox" v-model="item.checked" :checked="item.checked"> 28 </td> 29 <td>{{index + 1}}</td> 30 <td>{{item.name}}</td> 31 <td>{{item.price}}</td> 32 <td> 33 <button :disabled='item.count === 1' @click='handleReduce(index)'>-</button> 34 {{item.count}} 35 <button @click='handleAdd(index)'>+</button> 36 </td> 37 <td> 38 <button @click='handleRemove(index)'>移除</button> 39 </td> 40 </tr> 41 </tbody> 42 </table> 43 <div>总价: {{totalPrice}}</div> 44 </template> 45 <div v-else>购物车为空</div> 46 47 </div> 48 49 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 50 <script src="index.js"></script> 51 </body> 52 </html>
index.js
1 var app = new Vue({ 2 el: '#app', 3 data: { 4 list: [ 5 { 6 id: 1, 7 name: 'iPhone 7', 8 price: 6188, 9 count: 1, 10 checked: false 11 }, 12 { 13 id: 2, 14 name: 'iPad Pro', 15 price: 5888, 16 count: 1, 17 checked: true 18 }, 19 { 20 id: 3, 21 name: 'Macbook Pro', 22 price: 21488, 23 count: 1, 24 checked: false 25 } 26 ] 27 }, 28 computed: { 29 totalPrice: function () { 30 var total = 0; 31 for (var i = 0; i < this.list.length; i++) { 32 total += this.list[i].checked ? this.list[i].price * this.list[i].count : 0; 33 } 34 return total.toString().replace(/\B(?=(\d{3})+$)/g, ','); 35 }, 36 checkAll: { 37 get() { 38 var result = true; 39 for (var i = 0; i < this.list.length; i++) { 40 if (!this.list[i].checked) 41 result = false; 42 } 43 return result; 44 }, 45 set(val) { 46 for (var i = 0; i < this.list.length; i++) { 47 this.list[i].checked = val; 48 } 49 } 50 } 51 }, 52 methods: { 53 handleReduce: function (index) { 54 if (this.list[index].count === 1) return; 55 this.list[index].count--; 56 }, 57 58 handleAdd: function (index) { 59 this.list[index].count++; 60 }, 61 62 handleRemove: function (index) { 63 this.list.splice(index, 1); 64 }, 65 66 handleCheckAll: function () { 67 var setCheck = this.checkAll; 68 for (var i = 0; i < this.list.length; i++) { 69 var tmpObj = this.list[i]; 70 tmpObj.checked = setCheck; 71 this.$set(this.list, i, tmpObj); 72 } 73 } 74 } 75 })
style.css
1 [v-cloak]{ 2 display: none; 3 } 4 5 table { 6 border: 1px solid #e9e9e9; 7 border-collapse: collapse; 8 border-spacing: 0px; 9 empty-cells: show; 10 } 11 12 th, td{ 13 padding: 8px 16px; 14 border: 1px solid #e9e9e9; 15 text-align: left; 16 } 17 18 th{ 19 background: #f7f7f7; 20 color: #5c6b77; 21 font-weight: 600; 22 white-space: nowrap; 23 }