vue+bootstrap实现的购物车案例
效果图
功能
- 添加、减少或直接输入商品数量
- 移除商品
- 全选和非全选
- 计算总价格
- 清空购物车
- 人名和商品数量的排序
简单的代码实现
<!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"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.0/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/font-awesome/5.13.0/css/all.min.css"> <style> #app { padding: 20px; } </style> <title>Document</title> </head> <body> <div id="app"> <div> <h3>Cart</h3> <table class="table table-striped table-hover table-bordered text-center" style="font-size: 16px;"> <thead> <tr> <th scope="col"></th> <th scope="col" @click="sortName" :style="currentIndex === 1 ? {color: 'red'} : ''">Name<i class="fa fa-filter"></i></th> <th scope="col" @click="sortQuality" :style="currentIndex === 2 ? {color: 'red'} : ''">Quality<i class="fa fa-filter"></i></th> <th scope="col"><i>(standard)</i>Price<i>(USD)</i></th> <th scope="col">Sub-total(USD)</th> <th scope="col">Add/Sub</th> <th scope="col">Operation</th> </tr> </thead> <tbody> <tr v-for="(item, index) in list"> <td><input type="checkbox" :checked="item.checked" @change="handelItemChange(item.id)"></td> <td>{{item.name}}</td> <td>{{item.qty}}</td> <td>{{item.price | formatPrice}}</td> <td>{{item.price * item.qty | formatPrice}}</td> <td style="min- 120px;"> <button type="button" class="btn btn-outline-success" @click="decrement(index)" v-bind:disabled="item.qty <= 1">-</button> <input type="number" min="1" :value="item.qty" class="form-control" style=" 50px;display: inline-block;" @change="handelInput($event, index)"> <button type="button" class="btn btn-outline-success" @click="increment(index)">+</button> </td> <td><button type="button" class="btn btn-outline-danger" @click="removeHandle(index)">remove</button></td> </tr> <tr> <td><input type="checkbox" @change="selectAll" :checked="allChecked">all</td> <td colspan="2" style="font-weight: bolder;" class="text-ali">TotalNum:{{totalNum}}</td> <td colspan="2" style="font-weight: bolder;" class="text-ali">TotalPrice:{{totalPrice | formatPrice}}</td> <td colspan="2"><button type="button" class="btn btn-danger" @click="resetList">Reset</button> <button type="button" class="btn btn-primary" @click="checkPrice">Checkout</button></td> </tr> </tbody> </table> </div> <!-- <h2 v-else>Empty</h2> --> </div> <script src="http://vuejs.org/js/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { list: [ { id: 1, name: "Chicken Wing", category: "Food", qty: 3, price: 10, checked: true }, { id: 2, name: "Pizza", category: "Food", qty: 5, price: 50, checked: true }, { id: 3, name: "Hamburger", category: "Food", qty: 2, price: 12, checked: true }, { id: 4, name: "Coca Cola", category: "Drink", qty: 1, price: 5, checked: true }, { id: 5, name: "Orange Juice", category: "Drink", qty: 1, price: 15, checked: true }, { id: 6, name: "Potato Chips", category: "Snack", qty: 8, price: 8, checked: true }, ], allChecked: false, totalNum: 0, totalPrice: 0, // 当前选中的是哪个 currentIndex: null, }, methods: { increment(index) { this.list[index].qty++ this.setCart(this.list) }, decrement(index) { this.list[index].qty-- this.setCart(this.list) }, removeHandle(index) { let flag = confirm('您确定要删除吗?') if (flag) { this.list.splice(index, 1) this.setCart(this.list) } }, resetList() { let flag = confirm('Are you sure you want to empty your shopping cart?') if (flag) { this.list = [] this.allChecked = false this.setCart(this.list) this.currentIndex = null } }, checkPrice() { if (this.list.length > 0) { alert('Please pay: ' + this.totalPrice) } else { alert('Please select the product') } }, // 全选和非全选 selectAll() { this.allChecked = !this.allChecked this.list.forEach(item => item.checked = this.allChecked) this.setCart(this.list) }, // 单个商品的选中和不选中 handelItemChange(id) { // 找到对应的商品取反 const index = this.list.findIndex(item => item.id === id) this.list[index].checked = !this.list[index].checkedthis.setCart(this.list) }, setCart(list) { let num = 0 let price = 0 let select = true list.forEach(item => { if (item.checked) { num += item.qty price += item.price * item.qty } else { select = false } }) if (list.length === 0) { select = false } this.totalNum = num this.totalPrice = price this.allChecked = select }, // sort by name sortName() { this.currentIndex = 1 this.list.sort(function (a, b) { var nameA = a.name.toUpperCase(); // ignore upper and lowercase var nameB = b.name.toUpperCase(); // ignore upper and lowercase if (nameA < nameB) { return -1; } if (nameA > nameB) { return 1; } return 0; }) }, // sort by value sortQuality() { this.currentIndex = 2 this.list.sort((a, b) => { // 顺序排列 return (a.qty - b.qty) }) }, // 文本框输入数量 handelInput(e, index) { this.list[index].qty = parseInt(e.target.value) this.setCart(this.list) }, }, mounted() { this.allChecked = this.list.length ? this.list.every(item => item.checked) : false this.setCart(this.list) }, filters: { formatPrice(price) { return 'USD ' + price.toFixed(2) } }, }) </script> </body> </html>