1. HTML代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-size:16px;}
table{margin:15px 0;width:100%;border:1px solid #eee;border-collapse:collapse;text-align:center;}
table caption{padding:10px;border-top:5px solid #f08080;border-right:1px solid #eee;border-left:1px solid #eee;font-size:32px;}
table td,table th{padding:5px 8px;height:30px;border-bottom:1px solid #eee;line-height:30px;}
table tbody tr:hover{background-color:#eee;cursor:pointer;}
table tfoot,table thead{background-color:#fafafa;}
table tbody td[colspan="6"]{background-color:#fafafa;}
input[type=number]{padding:5px 3px;height:30px;border:solid 1px #eaeaea;text-align:center;line-height:30px;}
#app{margin:0 auto;width:960px;}
</style>
</head>
<body>
<div id="app">
<table class="cart">
<caption>购物车</caption>
<thead>
<tr>
<!-- 全选按钮 -->
<td><input type="checkbox" name="" class="check-all" checked/></td>
<td>编号</td>
<td>品名</td>
<td>单位</td>
<td>单价/元</td>
<td>库存</td>
<td>数量</td>
<td>金额(元)</td>
</tr>
</thead>
</table>
</div>
<script type="module">
import Cart from "./module/Cart.js"
const items = [
{ id: 286, name: '酸奶', units: '箱', price: 50, stock: 15, num: 1 },
{ id: 870, name: '苹果', units: '千克', price: 10, stock: 50, num: 1 },
{ id: 633, name: '外套', units: '件', price: 300, stock: 20, num: 1 },
{ id: 153, name: '皮鞋', units: '双', price: 400, stock: 10, num: 1 },
{ id: 109, name: '手机', units: '台', price: 5000, stock: 20, num: 0 },
];
const cart = new Cart(items);
//console.log(cart.getTotalMoney())
// console.log(cart.payMoney)
const table = document.querySelector('table');
const tbody = table.createTBody();
items.forEach(function(item, key) {
// 1. 创建商品模板字符串
const tr = `
<tr>
<td><input type="checkbox" name="" class="check-one" checked /></td>
<td>${item.id}</td>
<td>${item.name}</td>
<td>${item.units}</td>
<td>${item.price}</td>
<td class="stock">${cart.stockNum[key]}</td>
<td>
<input type="number" name="num" value="${item.num}" min="0" max="${item.stock}">
</td>
<td class="money">${cart.money[key]}</td>
</tr>
`;
// 2. 将内容填充到tbody
tbody.insertAdjacentHTML('beforeend', tr);
});
const tfoot = table.createTFoot();
// 创建tfoot内容
let tr = `
<tr>
<td rowspan="2" colspan="6">总计:</td>
<td rowspan="2" class="total">${cart.total}</td>
<td>
优惠: <span class="reduce">${cart.reduce}</span>元
</td>
</tr>
<tr>
<td>
原价: <span class="total-money" style="color: blue;">${cart.totalMoney}</span>元<br>
实付: <span class="pay-money" style="color: red;">${cart.payMoney}</span>元
</td>
</tr>
`;
tfoot.insertAdjacentHTML('beforeend', tr);
// 拿到所有的数量控件
const nums = table.querySelectorAll('[type=number]');
nums.forEach(function(num, key) {
num.oninput = function() {
// 1. 计算总数量
items[key].num = num.value * 1;
// if (items[key].num > items[key].stock) {
// alert(没有库存了);
// }
cart.total = cart.getTotal(items);
// 2. 计算每个商品金额
cart.money[key] = num.value * 1 * items[key].price;
// 3. 计算商品总金额
cart.totalMoney = cart.money.reduce(function(acc, cur) {
return acc + cur;
});
// 更新折扣和实付价格
cart.reduce = cart.getReduce(cart.totalMoney);
cart.payMoney = cart.totalMoney - cart.reduce;
//console.log(items[key].stock, num.value);
// 4. 计算库存
cart.stockNum[key] = parseInt(items[key].stock) - parseInt(num.value);
// 4. 将数据渲染到指定元素上
table.querySelector('.total').textContent = cart.total;
table.querySelectorAll('.money')[key].textContent = cart.money[key];
table.querySelector('.total-money').textContent = cart.totalMoney;
table.querySelector('.pay-money').textContent = cart.payMoney;
table.querySelector('.reduce').textContent = cart.reduce;
table.querySelectorAll('.stock')[key].textContent = cart.stockNum[key];
};
});
/**
* 全选事件
*/
// 全选选择器
const checkboxAll = table.querySelector('.check-all');
// 除了全选以外的节点
const checkboxList = table.querySelectorAll('[type="checkbox"]:not(.check-all)');
// 点击全选
checkboxAll.onclick = function() {
checkboxList.forEach(item => {
item.checked = checkboxAll.checked;
})
}
// 判断全选
checkboxList.forEach(item => {
item.onclick = () => {
//console.log(Array.from(checkboxList))
// 将节点转换对象, 判断是否选中
let chs = Array.from(checkboxList).filter(item => {
// 如果选中返回 true
return item.checked === true
});
//console.log(chs)
// 选中的长度等于全选的长度, 标记全选状态
checkboxAll.checked = checkboxList.length === chs.length;
}
})
</script>
</body>
</html>
2. JS模块: Cart.js
/**
* 购物车模块 Cart.js
*/
export default class {
// 构造器
constructor(items) {
// 1. 商品总数量
this.total = this.getTotal(items);
// 2. 每个商品金额(数组)
this.money = this.getMoney(items);
// 3. 商品总金额
this.totalMoney = this.getTotalMoney();
// 4. 剩余库存
this.stockNum = this.getStockNum(items);
// 5. 获取优惠折扣
this.reduce = this.getReduce();
// 6. 获取付款价格
this.payMoney = this.getPayMoney();
}
// (一) 计算商品总数量
getTotal(items) {
// 1. 数量数组: 每个商品的数量num字段组成的数组
let numArr = items.map(function(item) {
return item.num;
});
// 2. 计算总数量
return numArr.reduce(function(acc, cur) {
return acc + cur;
});
}
// (二) 计算每个商品的金额
getMoney(items) {
// 金额 = 数量 * 单价
return items.map(function(item) {
return item.num * item.price;
});
}
// (三) 计算商品总金额
getTotalMoney() {
return this.money.reduce(function(acc, cur) {
return acc + cur;
});
}
// (四) 计算库存
getStockNum(items) {
// 库存数组
let stockArr = items.map(function(item) {
return item.stock;
});
return items.map(function(item) {
return item.stock - item.num;
});
}
/**
* 还不会用去用遍历方式来计算判断, 暂时用静态参数判断吧
*/
getReduce(totalMoney) {
totalMoney = totalMoney || this.totalMoney;
let reduce = 0;
switch(true) {
case totalMoney >= 5000 :
reduce = 500;
break;
case totalMoney >= 2000 :
reduce = 300;
break;
case totalMoney >= 1000 :
reduce = 100;
break;
case totalMoney >= 800 :
reduce = 60;
break;
case totalMoney >= 500 :
reduce = 50;
break;
}
return reduce;
}
getPayMoney() {
return this.totalMoney - this.reduce;
}
}
3. 运行效果