1. JS实现购物车自动结算
1.1 html部分:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>购物车全选以及结算</title>
<link rel="stylesheet" href="demo2.css" />
</head>
<body>
<table class="shopping">
<caption>
<h3>购物车</h3>
</caption>
<thead>
<tr>
<th>
<input type="checkbox" name="checkAll" id="checkAll" checked />
<label for="">全选</label>
</th>
<th>ID</th>
<th>品名</th>
<th>单位</th>
<th>单价</th>
<th>数量</th>
<th>金额</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" name="checkOnly" checked /></td>
<td>1010</td>
<td>商品一</td>
<td>台</td>
<td>300</td>
<td><input type="number" name="shopNum" value="1" /></td>
<td></td>
</tr>
<tr>
<td><input type="checkbox" name="checkOnly" checked /></td>
<td>1010</td>
<td>商品二</td>
<td>台</td>
<td>500</td>
<td><input type="number" name="shopNum" value="1" /></td>
<td></td>
</tr>
<tr>
<td><input type="checkbox" name="checkOnly" checked /></td>
<td>1010</td>
<td>商品三</td>
<td>台</td>
<td>800</td>
<td><input type="number" name="shopNum" value="1" /></td>
<td></td>
</tr>
<tr>
<td><input type="checkbox" name="checkOnly" checked /></td>
<td>1010</td>
<td>商品四</td>
<td>台</td>
<td>1000</td>
<td><input type="number" name="shopNum" value="1" /></td>
<td></td>
</tr>
<tr>
<td><input type="checkbox" name="checkOnly" checked /></td>
<td>1010</td>
<td>商品五</td>
<td>台</td>
<td>2000</td>
<td><input type="number" name="shopNum" value="1" /></td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5">总计</td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
<div class="account">
<button>结算</button>
</div>
<script src="demo.js"></script>
</body>
</html>
1.2 CSS部分:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.shopping {
margin: auto;
width: 90%;
border: 1px solid;
text-align: center;
border-collapse: collapse;
}
.shopping th,
td {
border: 1px solid;
padding: 8px;
}
.shopping caption h3 {
padding: 10px;
}
.shopping thead tr {
background: lightcoral;
}
.shopping tbody tr:nth-of-type(even) {
background: lightcyan;
}
.account {
width: 90%;
margin: auto;
text-align: right;
padding-top: 10px;
}
.account button {
width: 100px;
padding: 5px;
background: green;
color: white;
outline: none;
border: none;
}
.account button:hover {
cursor: pointer;
background: rgb(5, 168, 5);
}
1.3 JS部分:
// 1. 实现全选和全不选效果
// 1.1 获取到全选项和下面的单选项
var checkAll = document.querySelector("#checkAll");
var checkOnlys = document.getElementsByName("checkOnly");
checkAll.addEventListener("change", checkAllBtn, false);
function checkAllBtn() {
checkOnlys.forEach(function (item) {
// 1.2 如果全选项的checked为true,下面所有单选项都为true,反之为false
item.checked = checkAll.checked;
var findNum = item.parentNode.parentNode.children.item(5).childNodes[0];
// 1.3 如果全选为false,数量单元被禁用,并且值全部为0
if (checkAll.checked) {
findNum.disabled = false;
} else {
findNum.disabled = true;
findNum.value = 0;
document.querySelector("tfoot tr td:nth-of-type(2)").innerHTML = 0;
findNum.parentNode.nextElementSibling.innerHTML = 0;
document.querySelector("tfoot tr td:last-of-type").innerHTML = 0;
}
});
}
// 2. 设置下面单个选项控制全选效果
checkOnlys.forEach(function (item) {
item.addEventListener("change", controlCheckAll, false);
});
function controlCheckAll(ev) {
// 2.1 获取到当前所有checked值为true单选项,用它的长度和单选项总的长度对比,如果长度一样,表示所有单选项被选中,那么设置全选想为true
// 反之,若长度不一样,说明至少有一个单选项没有checked,那么设置全选项为false
var checkedNum = document.querySelectorAll(
"input[type=checkbox]:not(#checkAll):checked"
);
checkAll.checked = checkOnlys.length === checkedNum.length;
// 2.2 设置取消单选项时,不要计算单元金额、总数量以及总金额
// 通过当前取消的单选项(ev.target),找到此选项对应的数量单元格,并将此单元格的value改为0
var findNum = ev.target.parentNode.parentNode.children.item(5).childNodes[0];
if (!ev.target.checked) {
findNum.value = 0;
findNum.disabled = true;
// 将取消的单元项的单元金额也设为0
findNum.parentNode.nextElementSibling.innerHTML = 0;
// 获取除取消的单元项以外的单元项,并计算它们的总数量以及总金额
var newNumSum = 0;
var newMoneySum = 0;
shoppingNums.forEach(function (item, index) {
newNumSum += parseInt(item.value);
});
totalNum.innerHTML = newNumSum;
unitMoneys.forEach(function (item, index) {
newMoneySum += parseInt(item.innerHTML);
});
totalMoney.innerHTML = newMoneySum;
} else {
findNum.disabled = false;
}
}
// 3. 监听数量的变化,从而动态改变单元金额、总金额和总数量的值
// 3.1 获取到所有的数量单元,金额单元,单价单元,总数量,总金额
var shoppingNums = document.getElementsByName("shopNum"); // 数量单元
var unitMoneys = document.querySelectorAll("tbody tr td:last-of-type"); // 金额单元
var units = document.querySelectorAll("tbody tr td:nth-of-type(5)"); //单价单元
var totalNum = document.querySelector("tfoot tr td:nth-of-type(2)"); //总数量
var totalMoney = document.querySelector("tfoot tr td:last-of-type"); //总金额
// 3.2 设置默认值
var numSum = 0;
var moneySum = 0;
unitMoneys.forEach(function (item, index) {
// 获取每个单元的金额
item.innerHTML = units[index].innerHTML * shoppingNums[index].value;
// 获取总的商品数量
numSum += parseInt(shoppingNums[index].value);
// 获取总的商品金额
moneySum += parseInt(unitMoneys[index].innerHTML);
});
totalNum.innerHTML = numSum;
totalMoney.innerHTML = moneySum;
// 3.3 监听数量在变化时,其他单元也动态变化
shoppingNums.forEach(function (item) {
item.addEventListener("input", changeAll, false);
});
function changeAll(ev) {
// 判断:当前变化的数量单元格必须是在被选中的状态下才能变化
if (ev.target.parentNode.parentNode.children.item(0).childNodes[0].checked) {
// 获取到数量变化时单元金额的变化
ev.target.parentNode.nextElementSibling.innerHTML =
ev.target.value * ev.target.parentNode.previousElementSibling.innerHTML;
var nowNumSum = 0;
var nowMoneySum = 0;
// 获取到数量变化时商品总数量的变化
shoppingNums.forEach(function (item, index) {
nowNumSum += parseInt(item.value);
});
totalNum.innerHTML = nowNumSum;
// 获取到数量变化时商品总金额的变化
unitMoneys.forEach(function (item, index) {
nowMoneySum += parseInt(item.innerHTML);
});
totalMoney.innerHTML = nowMoneySum;
}
}
1.4 效果如下:
- 全选和全不选效果以及取消任一单元项就取消全选:
- 全选状态下的自动结算:
- 取消单元项时,其他项也自动结算:
- 整体效果:
2. 总结
把这次作业当成了一次对自己的考核,没有看视频回放,也没有看老师的代码,全部自己写的,花了几个小时写完以后对照老师的代码,感觉不足之处还是在于对函数的利用,没有做得很好,充分利用好函数才能实现对代码的复用,可能自己的思想层面还没有达到那个程度,现在还停留在对一个方案的逻辑上面,必须再上一层,达到使用函数来构建逻辑,然后再组织代码。