功能示例图
1.商品的全选与取消全选
1.1 点击全选时,每个商品选择框全部激活;反之全部取消。
1.2 点击单个商品选择框时,会判断所所有商品选择框是否全部激活,全部激活则全选框激活,只要有一个选择框未激活,则全选框不激活。
2. 商品金额的计算
2.1 每个商品根据数量和单价计算单个商品总额,渲染到页面中
3.根据商品选择框是否激活,计算已激活的所以商品的数量和金额,渲染到页面中
<!DOCTYPE html>
<html lang="en">
<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>
<link rel="stylesheet" href="./style.css">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
</head>
<body>
<table>
<caption>
购物车
</caption>
<thead>
<tr>
<!-- 全选复选框 -->
<th><input type="checkbox" name="checkAll" id="check-all" /><label for="check-all">全选</label></th>
<th>图片</th>
<th>品名</th>
<th>单位</th>
<th>单价/元</th>
<th>数量</th>
<th>金额/元</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="checkbox" name="item" value="SN-1020" checked />
</td>
<td>
<a href=""><img src="images/1.gif" alt="" /></a>
</td>
<td>iPhone 11</td>
<td>台</td>
<td class="price">1</td>
<td><input type="number" min="1" value="1" /></td>
<td class="amount">xxx</td>
</tr>
<tr>
<td>
<input type="checkbox" name="item" value="SN-1020" checked />
</td>
<td>
<a href=""><img src="images/1.gif" alt="" /></a>
</td>
<td>小米pro 11</td>
<td>部</td>
<td class="price">2</td>
<td><input type="number" min="1" value="2" /></td>
<td class="amount">xxx</td>
</tr>
<tr>
<td>
<input type="checkbox" name="item" value="SN-1030" />
</td>
<td>
<a href=""><img src="images/1.gif" alt="" /></a>
</td>
<td>MacBook Pro</td>
<td>台</td>
<td class="price">3</td>
<td><input type="number" min="1" value="1" /></td>
<td class="amount">xxx</td>
</tr>
<tr>
<td>
<input type="checkbox" name="item" value="SN-1040" checked />
</td>
<td>
<a href=""><img src="images/1.gif" alt="" /></a>
</td>
<td>小米75电视</td>
<td>台</td>
<td class="price">4</td>
<td><input type="number" min="1" value="2" /></td>
<td class="amount">xxx</td>
</tr>
<tr>
<td>
<input type="checkbox" name="item" value="SN-1050" checked />
</td>
<td>
<a href=""><img src="images/1.gif" alt="" /></a>
</td>
<td>Canon 90D单反</td>
<td>台</td>
<td class="price">5</td>
<td><input type="number" min="1" value="1" /></td>
<td class="amount">xxx</td>
</tr>
</tbody>
<tfoot>
<tr style="font-weight: bolder; font-size: 1.2em">
<td colspan="5">总计:</td>
<td id="sum">xxx</td>
<td id="total-amount">xxx</td>
</tr>
</tfoot>
</table>
<div style="width: 90%; margin: 10px auto">
<button style="float: right; width: 100px">结算</button>
</div>
<script>
//1.获取全选和所有独立商品复选框
const checkAll = document.querySelector("#check-all");
const checkItems = document.getElementsByName("item");
// 为全选框添加事件:change(当值发生变化时会触发)
checkAll.onchange = function (ev) {
checkItems.forEach(function (item) {
item.checked = ev.target.checked;
})
//全选框取消或激活时需要触发自动计算
autoCalculate();
}
// 为每个单独的商品选择框添加change事件(每个商品都选择时,全选框被激活,否则取消)
checkItems.forEach(function (item) {
item.onchange = function () {
// Array.every(callback):对数组中每个成员进行回调处理,只有全部为true,最终才返回true,只要有一个返回false最终也会返回false,类似“逻辑与 and”;some()相反。
checkAll.checked = [...checkItems].every(item => item.checked);
//每次选中或取消单个商品选择框时需要触发自动计算
autoCalculate();
}
})
// 获取所以的数量控件
const numInput = document.querySelectorAll("tbody input[type=number]");
// 用户更新数量时自动触发自动计算
numInput.forEach(function (input) {
input.onchange = autoCalculate;
})
// 购物车刚加载完也要触发自动计算
window.onload = autoCalculate;
// 封装一个计算金额的函数
function autoCalculate() {
// 获取单价组成的数组
const prices = document.querySelectorAll("tbody .price");
const priceArr = [...prices].map(function (item) {
return item.textContent * 1;//结果为字符串,乘以1后会执行自动转换,转换成数字
})
// 获取数量组成的数组
const numbers = document.querySelectorAll("tbody input[type=number]");
const numberArr = [...numbers].map(function (item) {
return item.value * 1;//结果为字符串,乘以1后会执行自动转换,转换成数字
})
//计算每件商品金额,单价*数量
// 将金额数组和数量数组作为一个新的数组,reduce()将会对其内的两个数组都进行处理; total为最终返回值,curr为当前被操作的数组
const amountArr = [priceArr, numberArr].reduce(function (total, curr) {
return total.map(function (item, index) {
return item * curr[index];
})
})
//获取选中的商品数量的数组
let checkNumberArr = [];
[...numbers].map(function (item, index) {
// 如果当前商品选中,将商品数量取出
if (checkItems[index].checked) {
checkNumberArr[index] = item.value * 1;
}
})
//获取选中的商品价格的数组
let checkPriceArr = [];
[...prices].map(function (item, index) {
// 如果当前商品选中,将商品数量取出
if (checkItems[index].checked) {
checkPriceArr[index] = item.textContent * 1;
}
})
//计算每件选中商品的金额
const amountCheckedArr = [checkPriceArr, checkNumberArr].reduce(function (total, curr) {
return total.map(function (item, index) {
return item * curr[index];
})
})
//选中商品总数
let sum = 0;
if (checkNumberArr.length > 0) {
sum = checkNumberArr.reduce(function (pre, cur) {
return pre + cur;
})
}
// 计算选中商品总金额
let totalAmount = 0;
if (amountCheckedArr.length > 0) {
totalAmount = amountCheckedArr.reduce(function (pre, cur) {
return pre + cur;
});
}
// 将计算的结果渲染到购物车中
document.querySelector("#sum").textContent = sum;
// 总金额也渲染
if (totalAmount) {
document.querySelector("#total-amount").textContent = totalAmount;
} else {
document.querySelector("#total-amount").textContent = '0';
}
// 每个商品的金额也渲染
document.querySelectorAll(".amount").forEach(function (item, index) {
item.textContent = amountArr[index];
});
}
</script>
</body>
</html>
CSS
table {
border-collapse: collapse;
width: 90%;
text-align: center;
margin: auto;
}
table caption {
margin-bottom: 15px;
font-size: 1.5rem;
}
table th,
table td {
border-bottom: 1px solid #ccc;
padding: 5px;
font-weight: normal;
}
table thead tr:first-of-type {
background-color: #e6e6e6;
height: 3em;
}
table input[type="checkbox"] {
width: 1.5em;
height: 1.5em;
}
table tbody tr {
border-bottom: 1px solid #ccc;
}
table tbody tr:hover {
background-color: #f6f6f6;
cursor: pointer;
}
tbody img {
width: 3em;
}
tbody input[type="number"] {
width: 3em;
}
button {
width: 150px;
height: 30px;
outline: none;
border: none;
background-color: teal;
color: white;
letter-spacing: 5px;
}
button:hover {
opacity: 0.7;
cursor: pointer;
}