要求:
1.有已知购物车数据,渲染页面,根据每一个商品中的选中状态决定全选状态、总数量和总价格 2.点击全选按钮,改变所有购物车商品的选中状态
3.点击每一个商品状态以后,相应的改变全选状态(数量和总价也相应的改变)
注意:是change事件
易错点:当重新渲染页面以后,每一个input的事件会消失,需要重新选择每一个input并绑
事件。
css部分(略显粗糙)
<style>
* {
padding: 0;
margin: 0;
}
.box {
width: 910px;
margin: 100px auto;
}
p {
width: 910px;
height: 40px;
line-height: 40px;
display: flex;
justify-content: space-between;
border: 1px solid black;
}
p span {
display: inline-block;
width: 130px;
text-align: center;
}
ul {
width: 910px;
border: 1px solid black;
overflow: hidden;
}
li {
height: 80px;
list-style: none;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding-top: 10px;
padding-left: 20px;
border-bottom: 1px solid black;
}
li span {
display: inline-block;
width: 130px;
text-align: center;
}
li img {
width: 80px;
height: 80px;
background-color: aqua;
}
li .num {
width: 60px;
}
.le,
.ri {
width: 30px;
height: 30px;
font-size: 24px;
}
h4 {
margin-top: 10px;
margin-left: 50px;
}
h4 span {
display: inline-block;
width: 150px;
}
</style>
html部分
<div class="box">
<p>
<span>全选<input type="checkbox"id="All">
</span><span>商品</span><span>图片</span><span>详情</span>
<span>价格</span><span>数量</span><span>合计</span>
</p>
<ul>
<!-- <li>
<span><input type="checkbox" checked=""></span><span>小米12-1</span>
<img src="" alt=""><span>砂石黑4GB+64GB</span><span>500</span>
<span>10</span>
</li>
<li>
<span><input type="checkbox" checked=""></span><span>小米12-1</span>
<img src="" alt=""><span>砂石黑4GB+64GB</span><span>500</span>
<span>10</span>
</li> -->
</ul>
<h4><span class="zs">总计:</span> <span class="zj">总价:</span></h4>
</div>
核心JS渲染
<script>
let products = [
{
goods_name: '小米12-1',
goods_img: 'https://img12.360buyimg.com/n0/s80x80_jfs/t1/118064/27/12885/59959/5f17b7efE453f688d/5b33ac76b2aaea9b.jpg',
goods_price: '500',
goods_attr: '砂石黑4GB+64GB',
goods_num: 10,
goods_is_checked: true
},
{
goods_name: '小米12-2',
goods_img: 'https://img12.360buyimg.com/n0/s80x80_jfs/t1/118064/27/12885/59959/5f17b7efE453f688d/5b33ac76b2aaea9b.jpg',
goods_price: '510',
goods_attr: '砂石黑4GB+64GB',
goods_num: 50,
goods_is_checked: false
}
];
//获取主要元素
let ul = document.querySelector('ul');
let all = document.querySelector('#All');
//进行第一次渲染
XR();
all.onchange = function () {
products.forEach((item => {
item.goods_is_checked = this.checked
}))
XR();//重新渲染页面
}
//渲染页面
//把渲染函数封装起来便于以后调用
function XR() {
ul.innerHTML = products.reduce((s, item) =>
s + `<li> <span><input type="checkbox" ${item.goods_is_checked ? "checked" : ""}></span><span>${item.goods_name}</span>
<img src="${item.goods_img}" alt=""><span>${item.goods_attr}</span><span class="dj">${item.goods_price}</span>
<button class="le">-</button><span class="num">${item.goods_num}</span><button class="ri">+</button><span class="hj">5000</span>
</li>`
, '');
//在渲染函数内部调用其他函数来实现复杂的功能
Num();//调用计算总数功能
inpsAll();//全选控制单选
setCheck();//单选
Btns();//按钮的加减事件
};
//计算总价,总数量 将其封装为函数
function Num() {
//获取总价和总数量标签来操作
let zs = document.querySelector('.zs');
let zj = document.querySelector('.zj')
//因为我们要操作的是数据 所以先命名两个常量来暂时保存初始值为0
let qZs = 0, qZj = 0;
products.forEach((item) => {//遍历数据
//利用三元运算符来判断前面是否被勾选被勾选则把数量和价钱加上没有则加零
qZs += item.goods_is_checked ? item.goods_num : 0;
qZj += item.goods_is_checked ? item.goods_num * item.goods_price : 0;
})
//最后将常量中保存的值传给要添加值的目标元素
zs.innerHTML = `总数量:${qZs}`;
zj.innerHTML = `总价格:${qZj}`;
}
//复选 跟距数据判断全选框的勾选状态
function inpsAll() {
//这里是根据传的数据 goods_is_checked: false根据true或false来判断全选框的状态
//这里使用every来遍历元素是根据every的特性,只有全部都为真才返回true否则就返回false
all.checked = products.every((item) => item.goods_is_checked)
}
//单选的点击事件
function setCheck() {
//这里我们使用拓展运算符将其转换为数组
let checkBtns = [...document.querySelectorAll('ul input')];
//然后遍历数组给每个item添加事件,再根据index值来操作对应的数据
checkBtns.forEach((item, index) => {
//通过onchange来获取input的状态 最后重新渲染数据
item.onchange = function () {
products[index].goods_is_checked = this.checked;
XR();
}
})
}
//按钮点击事件
//这里按钮点击加减事件写的略显麻烦原理和单选点击事件相似
function Btns() {
let le = [...document.querySelectorAll('.le')];
let ri = [...document.querySelectorAll('.ri')];
let hj = [...document.querySelectorAll('.hj')];
let nums = document.querySelectorAll('.num')
//在我们更改完数据后记得看数据为什么类型,并将其中的数字转化为number类型
//不然上文会报错
// 点击按钮减少事件
le.forEach((item, index) => {
item.onclick = function () {
//在购物时一般购物车中至少含有一件商品因此我在这里添加了个判断是否为1,为1之后就不可减少了
nums[index].innerHTML == 1 ? nums[index].innerHTML : --nums[index].innerHTML;
//更改相对应的数据,在更改后注意数据类型
products[index].goods_num = parseFloat(nums[index].innerHTML)
hj[index].innerHTML = products[index].goods_num * products[index].goods_price
XR();
}
})
// 点击按钮增加事件 (同上)
ri.forEach((item, index) => {
item.onclick = function () {
nums[index].innerHTML == 1 ? nums[index].innerHTML : ++nums[index].innerHTML;
products[index].goods_num = parseFloat(nums[index].innerHTML)
hj[index].innerHTML = products[index].goods_num * products[index].goods_price
XR();
}
})
}
</script>
总结
在实现这个购物车功能时建议先分析要实现的功能,并将其写写为一块一块的最后调用即可。这只实现了基础的功能,这代码是简单代码封装起来相互调用后实现的复杂功能。这样写可以更加方便日后更改,更可以让代码看上去简洁。