模仿京东购物车实现加减操作
案例描述
如图所示,通过点击加号或者减号按钮会自动计算小计的价格。逻辑非常简单。
在线展示:https://antmoe.gitee.io/project/2020/04/18/shop.html
实现过程
逻辑非常简单,获取值计算即可。
- 为两个按钮分别绑定事件
- 改变值
- 返回
代码实现
加号与减号逻辑几乎一样,以加号示例。
首先我们得HTML结构为
<table id="cart">
<tr>
<th><input type="checkbox" name="" id="checkall"> 全选</th>
<th>商品</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th>操作</th>
</tr>
<tr>
<td><input type="checkbox" name="check"></td>
<td>【49元1件88元2件118元3件】富贵鸟春季新品长袖格子男 509灰色 XL</td>
<td>¥<span name="price">2599.00</span></td>
<td>
<button name="minus" disabled>-</button>
<input type="text" name="count" value="1">
<button name="add">+</button>
</td>
<td>¥<span name="subtotal">2599.00</span></td>
<td><a href="#" name="delete">删除</a></td>
</tr>
<tr>
<td><input type="checkbox" name="check"></td>
<td>【49元1件88元2件118元3件】富贵鸟春季新品长袖格子男 509灰色 XL</td>
<td>¥<span name="price">2599.00</span></td>
<td>
<button name="minus" disabled>-</button>
<input type="text" name="count" value="1">
<button name="add">+</button>
</td>
<td>¥<span name="subtotal">2599.00</span></td>
<td><a href="#" name="delete">删除</a></td>
</tr>
<tr>
<td><input type="checkbox" name="check"></td>
<td>【49元1件88元2件118元3件】富贵鸟春季新品长袖格子男 509灰色 XL</td>
<td>¥<span name="price">2599.00</span></td>
<td>
<button name="minus" disabled>-</button>
<input type="text" name="count" value="1">
<button name="add">+</button>
</td>
<td>¥<span name="subtotal">2599.00</span></td>
<td><a href="#" name="delete">删除</a></td>
</tr>
</table>应该找到每一个加号按钮,并分别为其绑定事件。并且我们需要知道用户到底点击的是哪一个按钮。
// 获取所有加号按钮 var addButtons = document.getElementsByName('add') for (var i = 0; i < addButtons.length; i++) { // 因为获取的按钮是一个集合,因此需要取出每一项来添加事件 var addButton = addButtons[i] // 为每个按钮添加点击事件,传入参数event addButton.onclick = function (event) {} }接下来要做的就是获取输入框,并改变其值
// 获取当前点击的按钮 var targetButton = event.target // 操作与之关联的input元素 (存在空白节点问题,所以需要连续向上取两次) var inputElement = targetButton.previousSibling.previousSibling // 获取数量(string类型需要转化为Number类型) var count = Number(inputElement.value) // 计算 count += 1 // 将值更新到页面 inputElement.value = count // 获取减按钮(这里需要判断减按钮是否可以被点击) var minuButton = inputElement.previousSibling.previousSibling if (count > 1) { minuButton.removeAttribute('disabled') } else { minuButton.setAttribute('disabled', 'disabled') }既然可以改变输入框内容了,那接下来就是要计算小计的价格了。
// 通过当前点击的按钮获取父级节点 var btnTdElement = targetButton.parentNode // 通过按钮的父级节点获取单价节点 var priTdElement = btnTdElement.previousSibling.previousSibling // 获取单价 var priceElement = priTdElement.childNodes[1] // 将单价转换为浮点型 var price = parseFloat(priceElement.firstChild.nodeValue) // 计算总值 var subtotal = price *= count // 判断是否有小数点,没有添加 if (String(subtotal).indexOf('.') === -1) { subtotal = subtotal + '.00' } // 通过按钮的父级节点获取下一个兄弟元素即总价节点 var subTdElement = btnTdElement.nextSibling.nextSibling // 获取总价 var subtotalElement = subTdElement.childNodes[1] // 改变总价的文本 subtotalElement.textContent = subtotal主要功能都完成了,接下来就是细节了,即最前边的复选框和背景颜色
// 通过按钮的父级节点获取父级节点 var trElement = btnTdElement.parentNode // 通过上一步找到的tr元素节点 获取第一个子节点即复选框节点 var checkTdElement = trElement.childNodes[1] // 获取复选框节点的input节点 var checkboxElement = checkTdElement.firstChild // 设置值 checkboxElement.setAttribute('checked', 'checked') // 将当前这一行的背景颜色修改 #fff4e8 trElement.style.backgroundColor = '#fff4e8'至于减按钮功能类似
for (var i = 0; i < minusButtons.length; i++) { var minusButton = minusButtons[i] minusButton.onclick = function (event) { var targetButton = event.target // 操作与之关联的input元素 var inputElement = targetButton.nextSibling.nextSibling console.log(inputElement) // 获取数量(string类型) var count = Number(inputElement.value) // 计算 count -= 1 // 将值更新到页面 inputElement.value = count // 计算小计 var btnTdElement = targetButton.parentNode var priTdElement = btnTdElement.previousSibling.previousSibling var priceElement = priTdElement.childNodes[1] var price = parseFloat(priceElement.firstChild.nodeValue) var subtotal = price *= count if (String(subtotal).indexOf('.') === -1) { subtotal = subtotal + '.00' } var subTdElement = btnTdElement.nextSibling.nextSibling var subtotalElement = subTdElement.childNodes[1] subtotalElement.textContent = subtotal // console.log(price) // 操作减按钮 if (count <= 1) { targetButton.setAttribute('disabled', 'disabled') // 复选框 var trElement = btnTdElement.parentNode var checkTdElement = trElement.childNodes[1] var checkboxElement = checkTdElement.firstChild checkboxElement.removeAttribute('checked') // 将当前这一行的背景颜色修改 #fff4e8 trElement.style.backgroundColor = 'white' } } }删除按钮
完成了加减后,删除按钮就很简单了。但是需要注意几点:
①删除的是当前所在按钮的父级,也就是tr标签
②删除后需要将上方的总数修改-1
③就是a标签的跳转
// 删除按钮 var delButtons = document.getElementsByName("delete") for (var i = 0; i < delButtons.length; i++) { var delButton = delButtons[i] delButton.onclick = function (event) { var targetButton = event.target var currentTrElement = targetButton.parentNode.parentNode var parentElement = currentTrElement.parentNode parentElement.removeChild(currentTrElement) //修改上方总数量 var numberElement = document.getElementById('number') var number = parseInt(numberElement.textContent) number -= 1 numberElement.textContent = number /* 阻止a标签跳转 1. 通过调用调用 preventDefault() 2. 时间的处理函数 return 语句 -> return false */ event.preventDefault() } }全选
tip:判断复选框的
checked属性即可知道是否被选择。var checkall = document.getElementById("checkall") checkall.onclick = function () { console.log(1) console.log(checkall.checked) var checkElements = document.getElementsByName("check") var cart = document.getElementById('cart') var trElements = cart.getElementsByTagName('tr') if (checkall.checked) { for (var i = 0; i < checkElements.length; i++) { var checkElement = checkElements[i] checkElement.setAttribute("checked", "checked") } for (var i = 1; i < trElements.length; i++) { var trElement = trElements[i] trElement.style.backgroundColor = '#fff4e8' } } else { for (var i = 0; i < checkElements.length; i++) { var checkElement = checkElements[i] checkElement.removeAttribute('checked') } for (var i = 1; i < trElements.length; i++) { var trElement = trElements[i] trElement.style.backgroundColor = 'transparent' } } }
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车案例</title>
<style>
* {
box-sizing: border-box;
}
.cart-container {
margin: 100px auto;
width: 990px;
}
#title {
width: 100px;
color: #c81623;
padding: 10px 0px;
margin: 0;
border-bottom: 1px solid #c81623;
}
#cart {
width: 990px;
border: 1px solid #d9d9d9;
border-collapse: collapse;
}
#cart th,
#cart td {
height: 80px;
border-bottom: 1px solid #d9d9d9;
text-align: center;
}
#cart th {
background: #d9d9d9;
}
#cart td:nth-of-type(1) {
width: 60px;
text-align: center;
}
#cart td:nth-of-type(2) {
width: 400px;
}
#cart td:nth-of-type(3) {
width: 80px;
text-align: right;
}
#cart td:nth-of-type(4) {
width: 250px;
padding: 0 80px;
}
#cart td:nth-of-type(5) {
width: 80px;
text-align: right;
}
#cart td:nth-of-type(6) {
/* width: 80px; */
text-align: center;
}
#cart td:nth-of-type(4) button,
#cart td:nth-of-type(4) input {
display: block;
float: left;
height: 25px;
border: 1px solid #d9d9d9;
}
#cart td:nth-of-type(4) button {
width: 20px;
background-color: #fff;
}
#cart td:nth-of-type(4) input {
padding: 0;
border-width: 1px;
border-left: none;
border-right: none;
width: 50px;
outline: none;
text-align: center;
}
#cart td:nth-of-type(4) input:focus {
background-color: #f1f1f1;
}
#cart td a {
text-decoration: none;
color: #333333;
}
#cart td a:hover {
color: #c81623;
}
</style>
</head>
<body>
<div class="cart-container">
<!-- 购物车标题+商品数量 -->
<h3 id="title">全部商品<span id="number">3</span></h3>
<!-- 购物车表格 -->
<table id="cart">
<tr>
<th><input type="checkbox" name="" id="checkall"> 全选</th>
<th>商品</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th>操作</th>
</tr>
<tr>
<td><input type="checkbox" name="check"></td>
<td>【49元1件88元2件118元3件】富贵鸟春季新品长袖格子男 509灰色 XL</td>
<td>¥<span name="price">2599.00</span></td>
<td>
<button name="minus" disabled>-</button>
<input type="text" name="count" value="1">
<button name="add">+</button>
</td>
<td>¥<span name="subtotal">2599.00</span></td>
<td><a href="#" name="delete">删除</a></td>
</tr>
<tr>
<td><input type="checkbox" name="check"></td>
<td>【49元1件88元2件118元3件】富贵鸟春季新品长袖格子男 509灰色 XL</td>
<td>¥<span name="price">2599.00</span></td>
<td>
<button name="minus" disabled>-</button>
<input type="text" name="count" value="1">
<button name="add">+</button>
</td>
<td>¥<span name="subtotal">2599.00</span></td>
<td><a href="#" name="delete">删除</a></td>
</tr>
<tr>
<td><input type="checkbox" name="check"></td>
<td>【49元1件88元2件118元3件】富贵鸟春季新品长袖格子男 509灰色 XL</td>
<td>¥<span name="price">2599.00</span></td>
<td>
<button name="minus" disabled>-</button>
<input type="text" name="count" value="1">
<button name="add">+</button>
</td>
<td>¥<span name="subtotal">2599.00</span></td>
<td><a href="#" name="delete">删除</a></td>
</tr>
</table>
</div>
<!-- 结算 -->
<script>
// 获取到购物车中所有加按钮
var addButtons = document.getElementsByName('add')
var minusButtons = document.getElementsByName('minus')
console.log(minusButtons)
// 事件的绑定 -> 每次只能绑定一个元素
for (var i = 0; i < addButtons.length; i++) {
var addButton = addButtons[i]
// 绑定鼠标事件
// 修改数量
addButton.onclick = function (event) {
console.log('click')
/*
通过event对象获取用户点击的是哪个按钮
* 绑定事件的元素 -> 所有的<botton name='add'>+</botton>
* 触发事件的元素 -> 只能有一个
*/
// console.log(event.currentTarget, event.target, this)
var targetButton = event.target
// 操作与之关联的input元素
var inputElement = targetButton.previousSibling.previousSibling
// console.log(inputElement)
// 获取数量(string类型)
var count = Number(inputElement.value)
// 计算
count += 1
// 将值更新到页面
inputElement.value = count
// 操作与之关联的减按钮
var minuButton = inputElement.previousSibling.previousSibling
if (count > 1) {
minuButton.removeAttribute('disabled')
} else {
minuButton.setAttribute('disabled', 'disabled')
}
// 更新与之关联的小计
// 获取单价
var btnTdElement = targetButton.parentNode
var priTdElement = btnTdElement.previousSibling.previousSibling
var priceElement = priTdElement.childNodes[1]
var price = parseFloat(priceElement.firstChild.nodeValue)
var subtotal = price *= count
if (String(subtotal).indexOf('.') === -1) {
subtotal = subtotal + '.00'
}
var subTdElement = btnTdElement.nextSibling.nextSibling
var subtotalElement = subTdElement.childNodes[1]
subtotalElement.textContent = subtotal
// console.log(price)
// 复选框
var trElement = btnTdElement.parentNode
var checkTdElement = trElement.childNodes[1]
var checkboxElement = checkTdElement.firstChild
checkboxElement.setAttribute('checked', 'checked')
// 将当前这一行的背景颜色修改 #fff4e8
trElement.style.backgroundColor = '#fff4e8'
}
}
for (var i = 0; i < minusButtons.length; i++) {
var minusButton = minusButtons[i]
minusButton.onclick = function (event) {
var targetButton = event.target
// 操作与之关联的input元素
var inputElement = targetButton.nextSibling.nextSibling
console.log(inputElement)
// 获取数量(string类型)
var count = Number(inputElement.value)
// 计算
count -= 1
// 将值更新到页面
inputElement.value = count
// 计算小计
var btnTdElement = targetButton.parentNode
var priTdElement = btnTdElement.previousSibling.previousSibling
var priceElement = priTdElement.childNodes[1]
var price = parseFloat(priceElement.firstChild.nodeValue)
var subtotal = price *= count
if (String(subtotal).indexOf('.') === -1) {
subtotal = subtotal + '.00'
}
var subTdElement = btnTdElement.nextSibling.nextSibling
var subtotalElement = subTdElement.childNodes[1]
subtotalElement.textContent = subtotal
// console.log(price)
// 操作减按钮
if (count <= 1) {
targetButton.setAttribute('disabled', 'disabled')
// 复选框
var trElement = btnTdElement.parentNode
var checkTdElement = trElement.childNodes[1]
var checkboxElement = checkTdElement.firstChild
checkboxElement.removeAttribute('checked')
// 将当前这一行的背景颜色修改 #fff4e8
trElement.style.backgroundColor = 'white'
}
}
}
// 删除按钮
var delButtons = document.getElementsByName("delete")
for (var i = 0; i < delButtons.length; i++) {
var delButton = delButtons[i]
delButton.onclick = function (event) {
var targetButton = event.target
var currentTrElement = targetButton.parentNode.parentNode
var parentElement = currentTrElement.parentNode
parentElement.removeChild(currentTrElement)
var numberElement = document.getElementById('number')
var number = parseInt(numberElement.textContent)
number -= 1
numberElement.textContent = number
/*
阻止a标签跳转
1. 通过调用调用 preventDefault()
2. 时间的处理函数 return 语句 -> return false
*/
event.preventDefault()
}
}
// 全选
var checkall = document.getElementById("checkall")
checkall.onclick = function () {
console.log(1)
console.log(checkall.checked)
var checkElements = document.getElementsByName("check")
var cart = document.getElementById('cart')
var trElements = cart.getElementsByTagName('tr')
if (checkall.checked) {
for (var i = 0; i < checkElements.length; i++) {
var checkElement = checkElements[i]
checkElement.setAttribute("checked", "checked")
}
for (var i = 1; i < trElements.length; i++) {
var trElement = trElements[i]
trElement.style.backgroundColor = '#fff4e8'
}
} else {
for (var i = 0; i < checkElements.length; i++) {
var checkElement = checkElements[i]
checkElement.removeAttribute('checked')
}
for (var i = 1; i < trElements.length; i++) {
var trElement = trElements[i]
trElement.style.backgroundColor = 'transparent'
}
}
}
</script>
</body>
</html> 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小康博客!
评论
TwikooDisqusjs










