一个简单的购物车功能:
-
显示并列出产品的各项参数(商品名称,商品单价,购买数量,是否从购物车拿走,以及选择功能)
-
购买数量必须是大于等于1,如果不想购买,可以通过单击“移除”按钮,删除商品
-
显示全部产品的总价
-
显示选中的产品的总价
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"> <!--PC端必选 强制360浏览器使用webkit渲染 --> <meta name="renderer" content="webkit"> <link rel="stylesheet" type="text/css" href="css.css"> <title>购物车</title> <style> table { border: 1px solid #ccc; } thead { background-color: #ddd; } td { border: 1px solid #ccc; } [v-cloak]{ display: none } </style> </head> <body> <div> <p>购物车需求</p> <ol> <li>展示已经加入购物车的商品列表</li> <li>商品列表包含商品名称,商品单价,购买数量和操作能力</li> <li>能够实时显示所购买的总价</li> <li>商品数量可以增加,减少或者直接移除</li> </ol> </div> <hr> <!-- 页面挂载点 --> <div id="app" v-cloak> <template v-if="goods.length"> <table> <thead> <tr> <td>表头</td> <td>商品名称</td> <td>商品单价</td> <td>购买数量</td> <td>操作</td> <td>全选<input type="checkbox" @click="checkAll" id="checkAll" :checked="isCheckedAll"></td> </tr> </thead> <tbody> <tr v-for="(good,index) in goods"> <td>{{index+1}}</td> <td>{{good.name}}</td> <td>{{good.price}}</td> <!-- 数量调整 --> <td> <button @click="reduce(index)" :disabled="good.count === 1">-</button> {{good.count}} <button @click="add(index)">+</button> </td> <!-- 操作 --> <td> <button @click="remove(index)">移除</button> </td> <td> <!-- 单选 --> <input type="checkbox" @click="check(index,$event)" :checked="good.isChecked"> </td> </tr> </tbody> </table> <div><p> 全部总价:¥{{totalPrice}}</p> <p>选中总价: ¥{{checkedPrice}}</p> </div> </template> <div v-else>购物车是空的</div> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#app', data: { //商品数据 goods: [ { id: 1, name: 'iphone 7', price: 6188, count: 1, isChecked: false }, { id: 2, name: 'ipad Pro', price: 5888, count: 1, isChecked: false }, { id: 3, name: 'MacBook Pro', price: 21488, count: 1, isChecked: false }, { id: 4, name: 'iPod', price: 588, count: 1, isChecked: false } ], }, computed: { totalPrice: function() { var total = 0; //遍历相加 this.goods.forEach(function(item, index) { total += item.price * item.count; }) return total; }, //是否全选 isCheckedAll: function() { var flag = true; //遍历数组选项 this.goods.forEach(function(item, index) { //数组项没有选中 if (!item.isChecked) { flag = false; } }) return flag; }, //选中的产品价格 checkedPrice: function() { var total = 0; this.goods.forEach(function(item, index) { if (item.isChecked) { total += item.price * item.count; } }) return total; } }, methods: { reduce: function(index) { //再次判断 reduce 减法的可靠性 if (this.goods[index].count === 1) return; this.goods[index].count--; }, add: function(index) { this.goods[index].count++; }, remove: function(index) { //删除一条数组数据 this.goods.splice(index, 1); }, //全部选择 checkAll: function() { this.goods.forEach(function(item, index) { item.isChecked = !item.isChecked; //console.log(item.isChecked); }) }, check: function(index, event) { this.goods[index].isChecked = !this.goods[index].isChecked; } }, }) </script> </body> </html>
难点思路说明:
-
全选按钮绑定了一个计算属性isCheckedAll,这个属性的最终取值"true|false",是根据全部子选项的选择状态而确定的,如果选全部的子选项是选中的,则该属性是true,如果不是全部选中的,则是false。那么如何判断子选取的状态呢?通过JS原生的forEach方法,该方法针对数组元素有遍历功能,所以通过对数组goods的遍历来做判断即可:
isCheckedAll: function() { var flag = true; //遍历数组选项 this.goods.forEach(function(item, index) { //数组项没有选中 if (!item.isChecked) { flag = false; } }) return flag; }
forEach里面的item和index分别代表数组项和索引,这里item指代每个产品项对象,比如{ id: 1, name: 'iphone 7', price: 6188, count: 1, isChecked: false }
2.如何实现全选/反全选功能?和前面的思路一样,当点击全选按钮的时候子选项的状态全部变化,再次点击又再次变化,全选按钮实现的其实就是子选项的两种状态切换:
checkAll: function() { this.goods.forEach(function(item, index) { item.isChecked = !item.isChecked; //console.log(item.isChecked); }) },
也是遍历每个对象,然后取反。
3.单个子选项的点击切换和上面的类似,但是要求在用v-for渲染列表的时候必须显示的写出每个对象的索引(index)
<tr v-for="(good,index) in goods">
然后再通过函数传入方法内:
check: function(index) { this.goods[index].isChecked = !this.goods[index].isChecked; }
这里的index是指向当下点击的那个checkbox按钮,那么this.goods[index]也就指向了对应的数据对象