一. 购物车案例

1.1 案例介绍

今天我们来写另外一个购物车案例,说实话对于我来说这个是花了将近三个小时的时间然后才做出来的,里面可能还存在一些我没有发现的问题,但是能完成基本的功能,对于一些基本的需求都是可以完成的,下面照旧是案例实现的gif图片

根据上图我们可以看到,每个购物车的选项都是互不影响的,每个商店也都是互不影响的,单独运算,每个店的总计也是单独计算的,有一个计算复选框总价的功能,而且这是个通用的模板,不论有多少个店铺,店铺里面的商品有多少个,只要html的结构不变都是可以通用的,那么不多说,下面开始分析案例!

1.2 案例分析

下面给出相应的html结构的代码,便于我们进行分析

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
<title>购物车</title><link type="text/css" rel="stylesheet" href="css/base.css" />
<link type="text/css" rel="stylesheet" href="css/module.css"  /></head>
<body><!--头部开始-->
<div class="header"><h1>购物车</h1><a href="#" class="back"><span></span></a><a href="#" class=""></a>
</div>
<!--头部结束-->
<div class="shopping"><div class="shop-group-item"><div class="shop-name"><input type="checkbox" class="check goods-check shopCheck"><h4><a href="#">苹果专卖店</a></h4><div class="coupons"><span>领券</span><em>|</em><span>编辑</span></div></div><ul><li><div class="shop-info"><input type="checkbox" class="check goods-check goodsCheck"><div class="shop-info-img"><a href="#"><img src="data:images/computer.jpg" /></a></div><div class="shop-info-text"><h4>Apple MacBook Air 13.3英寸笔记本电脑 银色(Core i5 处理器/8GB内存/128GB SSD闪存 MMGF2CH/A)</h4><div class="shop-brief"><span>重量:3.3kg</span><span>颜色:银色</span><span>版本:13.3英寸</span></div><div class="shop-price"><div class="shop-pices">¥<b class="price">5899.00</b></div><div class="shop-arithmetic"><a href="javascript:;" class="minus">-</a><input class="num" value="1"/><a href="javascript:;" class="plus">+</a></div></div></div></div></li><li><div class="shop-info"><input type="checkbox" class="check goods-check goodsCheck"><div class="shop-info-img"><a href="#"><img src="data:images/ipad.jpg" /></a></div><div class="shop-info-text"><h4>Apple iPad Pro 平板电脑 10.5 英寸(64G WLAN版/A10X芯片/Retina屏/Multi-Touch技术 MQDX2CH/A)金色</h4><div class="shop-brief"><span>重量:0.85kg</span><span>颜色:金色</span><span>版本:64G WLAN版</span></div><div class="shop-price"><div class="shop-pices">¥<b class="price">4788.00</b></div><div class="shop-arithmetic"><a href="javascript:;" class="minus">-</a><input class="num" value="1"/><a href="javascript:;" class="plus">+</a></div></div></div></div></li><li><div class="shop-info"><input type="checkbox" class="check goods-check goodsCheck"><div class="shop-info-img"><a href="#"><img src="data:images/iphone.jpg" /></a></div><div class="shop-info-text"><h4>苹果 iPhone7 Plus 手机 红色特别版 全网通 128GB</h4><div class="shop-brief"><span>重量:0.18kg</span><span>颜色:红色特别版</span><span>版本:全网通 128G</span></div><div class="shop-price"><div class="shop-pices">¥<b class="price">6326.00</b></div><div class="shop-arithmetic"><a href="javascript:;" class="minus">-</a><input class="num" value="1"/><a href="javascript:;" class="plus">+</a></div></div></div></div></li></ul><div class="shopPrice">本店总计:¥<span class="shop-total-amount ShopTotal">0.00</span></div></div><div class="shop-group-item"><div class="shop-name"><input type="checkbox" class="check goods-check shopCheck"><h4><a href="#">小米专卖店</a></h4><div class="coupons"><span>领券</span><em>|</em><span>编辑</span><!--<span class="shop-total-amount ShopTotal">0</span>--></div></div><ul><li><div class="shop-info"><input type="checkbox" class="check goods-check goodsCheck"><div class="shop-info-img"><a href="#"><img src="data:images/computer.jpg" /></a></div><div class="shop-info-text"><h4>小米(MI)小米电视4A 标准版 65英寸 HDR 2GB+8GB 四核64位高性能处理器 4K超高清智能语音网络液晶平板电视机(L65M5-AZ)</h4><div class="shop-brief"><span>重量:16.3kg</span><span>颜色:黑色</span><span>版本:4A标准版</span></div><div class="shop-price"><div class="shop-pices">¥<b class="price">5999.00</b></div><div class="shop-arithmetic"><a href="javascript:;" class="minus">-</a><input class="num" value="1"/><a href="javascript:;" class="plus">+</a></div></div></div></div></li><li><div class="shop-info"><input type="checkbox" class="check goods-check goodsCheck"><div class="shop-info-img"><a href="#"><img src="data:images/computer.jpg" /></a></div><div class="shop-info-text"><h4>小米(MI) 定制版Ninebot 九号平衡车 智能代步电动体感车(白)</h4><div class="shop-brief"><span>重量:15.9kg</span><span>颜色:白色</span><span>版本:标准版</span></div><div class="shop-price"><div class="shop-pices">¥<b class="price">1949.00</b></div><div class="shop-arithmetic"><a href="javascript:;" class="minus">-</a><input class="num" value="1"/><a href="javascript:;" class="plus">+</a></div></div></div></div></li></ul><div class="shopPrice">本店总计:¥<span class="shop-total-amount ShopTotal">0.00</span></div></div><div class="shop-group-item"><div class="shop-name"><input type="checkbox" class="check goods-check shopCheck"><h4><a href="#">苹果专卖店</a></h4><div class="coupons"><span>领券</span><em>|</em><span>编辑</span></div></div><ul><li><div class="shop-info"><input type="checkbox" class="check goods-check goodsCheck"><div class="shop-info-img"><a href="#"><img src="data:images/computer.jpg" /></a></div><div class="shop-info-text"><h4>Apple MacBook Air 13.3英寸笔记本电脑 银色(Core i5 处理器/8GB内存/128GB SSD闪存 MMGF2CH/A)</h4><div class="shop-brief"><span>重量:3.3kg</span><span>颜色:银色</span><span>版本:13.3英寸</span></div><div class="shop-price"><div class="shop-pices">¥<b class="price">5899.00</b></div><div class="shop-arithmetic"><a href="javascript:;" class="minus">-</a><input class="num" value="1"/><a href="javascript:;" class="plus">+</a></div></div></div></div></li><li><div class="shop-info"><input type="checkbox" class="check goods-check goodsCheck"><div class="shop-info-img"><a href="#"><img src="data:images/ipad.jpg" /></a></div><div class="shop-info-text"><h4>Apple iPad Pro 平板电脑 10.5 英寸(64G WLAN版/A10X芯片/Retina屏/Multi-Touch技术 MQDX2CH/A)金色</h4><div class="shop-brief"><span>重量:0.85kg</span><span>颜色:金色</span><span>版本:64G WLAN版</span></div><div class="shop-price"><div class="shop-pices">¥<b class="price">4788.00</b></div><div class="shop-arithmetic"><a href="javascript:;" class="minus">-</a><input class="num" value="1"/><a href="javascript:;" class="plus">+</a></div></div></div></div></li><li><div class="shop-info"><input type="checkbox" class="check goods-check goodsCheck"><div class="shop-info-img"><a href="#"><img src="data:images/iphone.jpg" /></a></div><div class="shop-info-text"><h4>苹果 iPhone7 Plus 手机 红色特别版 全网通 128GB</h4><div class="shop-brief"><span>重量:0.18kg</span><span>颜色:红色特别版</span><span>版本:全网通 128G</span></div><div class="shop-price"><div class="shop-pices">¥<b class="price">6326.00</b></div><div class="shop-arithmetic"><a href="javascript:;" class="minus">-</a><input class="num" value="1"/><a href="javascript:;" class="plus">+</a></div></div></div></div></li></ul><div class="shopPrice">本店总计:¥<span class="shop-total-amount ShopTotal">0.00</span></div></div>
</div><div class="payment-bar"><div class="all-checkbox"><input type="checkbox" class="check goods-check" id="AllCheck">全选</div><div class="shop-total"><strong>总价:<i class="total" id="AllTotal">0.00</i></strong><span>减免:123.00</span></div><a href="#" class="settlement">结算</a>
</div>
</body>
<script src="js/index.js"></script>
</html>

这个HTML文件不是我写的,只是一个案例的小样,这篇我们主要编写的是JS,对html和css没有任何操作

通过上面的html结构我们可以看出,每个商店都有一个class属性为.shop-group-item的div标签包裹住,每个商店里面的购物项都有一个li标签包裹住,那么我们就可以知道如果我们根据.shop-group-item和li标签获取DOM元素的话,得到的肯定不是一个唯一值,而是一个数组值

所以首先我们需要将他们区分开,那么怎么区分开呢,这个时候涉及到一个知识点,获取当前标签下面的父元素节点,然后通过这个父元素节点对于整个元素进行操作,这样就可以得到我们要获取的唯一值了,整个案例的核心思想就是这个,通过多个子节点获取唯一父节点的DOM对象,然后根据这个父节点完成我们的需求操作。

1.3 代码编写

1.3.1 商品数量添加的处理

再写复选框之前,我们先对商品数量添加的处理,因为这个涉及到求和的问题,所以我们需要先计算出她所需要求的数量才能走到求和的问题

/*计算value值*/
//获取减号按钮
let minus = document.querySelectorAll('.shop-group-item .shop-info .shop-price .minus');
//获取加号按钮
let plus = document.querySelectorAll('.shop-group-item .shop-info .shop-price .plus');
for (let i = 0; i < plus.length; i++) {/*加法的计算*/plus[i].onclick = function () {//通过点击的元素获取到value值let num = parseInt(this.parentElement.querySelector('.num').value);console.log(num);this.parentElement.querySelector('.num').value = num + 1;//获取到当前节点下的所有复选框getSumByCheck(this);getSum();}/*减法计算*/minus[i].onclick = function () {//通过点击的元素获取到value值let num = parseInt(this.parentElement.querySelector('.num').value);console.log(num);//判断如果num的最小值为0if (num > 0) {this.parentElement.querySelector('.num').value = num - 1;}//获取到当前节点下的所有复选框getSumByCheck(this);getSum();}
}

以上就是对于加号减号的处理,求数量的处理

1.3.2 求和处理

这里的求和处理我封装成了两个方法,之前本来想封装成一个方法的,但是发现方法并不能通用,封装成两个方法也比较好处理

一个是求总价的方法

/*总价求和*/
function getSum() {//先获取每个infolet infos = document.querySelectorAll('.shop-group-item .shop-info');//设置总价格let totalCash = 0;for (let i = 0; i < infos.length; i++) {//再获取对应个info下面的价格let money = parseFloat(infos[i].querySelector('.price').innerText);//console.log(money);//获取对应info下面的value值let value = parseInt(infos[i].querySelector('.num').value);//console.log(value);//获取到复选框对象let check = infos[i].querySelector('.check');//如果被选中的话就进行计算if (check.checked) {totalCash += money * value;}/*infos[i].closest('.shop-group-item').querySelector('.shopPrice .shop-total-amount').innerText = totalCash;*/}document.querySelector('.payment-bar .total').innerText = totalCash;//将总价放在每一个总计标签里面
}

一个是求每个商店价格的方法,这个需要传进当前操作的this对象

/*根据check子节点求和*/
function getSumByCheck(_this) {//其实我们传过来的所有this对象他们都是有一个共同的父级,也就是shop-group-item这个div标签//上面有个对于总复选框进行判断的一个点击事件,之所以没有使用这个方法的原因是,他和shop-group-item这个div标签是平级的,所以无法获取到这个DOM对象,所以就把他单拎出来了let item = _this.closest('.shop-group-item');//获取到当前this对象对应的shop-group-item下的所有复选框let check = item.querySelectorAll('.shop-info .check');//初始化总价let totalCash = 0;//遍历求和for (let j = 0; j < check.length; j++) {//获取每一个的单价let money = parseFloat(check[j].closest('.shop-info').querySelector('.price').innerText);//获取每一个的数量let count = parseInt(check[j].closest('.shop-info').querySelector('.num').value);//判断是否被选中,被选中则进入计算if (check[j].checked) {totalCash += money * count;}}//将总价添加到本店总计里面item.querySelector('.shopPrice .shop-total-amount').innerText = totalCash;
}

这里取巧的就是利用他操作的每一个复选框他都有一个共同的父级元素,然后再对父级元素进行操作。

1.3.3 购物项复选框选中的处理

通过上面的分析,我们可以先获取所有的购物项对象,然后遍历购物项对象,并且将其遍历绑定点击事件

下面是代码

//通过单个点击获取到所有,获取到所有的购物项
let checks = document.querySelectorAll('.shop-group-item ul li .check');
//遍历所有购物项,目的是给所有购物项里面的某一个购物项绑定点击事件,然后获取他的唯一父元素
for (let i = 0; i < checks.length; i++) {//绑定点击事件,你点击哪一个,咱就能获取到哪一个的商店的头复选框checks[i].onclick = function () {//通过选中的复选框找到当前节点下itemlet item = this.closest('.shop-group-item');console.log(item);//再通过item来获取到当前节点下有多少个复选框let check = item.querySelectorAll('ul li .check');console.log(check.length);//通过item获取到当前节点下的总复选框let checkTotal = item.querySelector('.shop-name .check');console.log(checkTotal);//这里相当于是一个监听的效果,每点击一次,就会监听当前点击对象对应的父对象下面的子复选框是否全部被选中//说白了也就是判断当前点击元素平级的复选框是否全部被选中let checkNum = 0;for (let j = 0; j < check.length; j++) {//如果被选中一个,那么checkNum就会自动+1if (check[j].checked) {checkNum += 1;}}//如果当前点击元素平级的复选框被选中的值和该数组的长度一样的话,就让当前商店的头复选框选中checkTotal.checked = checkNum === check.length;//这里也相当于是一个监听的效果,每点击一次监听一下所有的购物项的复选框是否被选中let allCheckNum = 0;for (let j = 0; j < checks.length; j++) {//如果被选中的话就+1if (checks[j].checked) {allCheckNum += 1;}}console.log('allCheckNum:' + allCheckNum);//如果当前所有购物项被选中的复选框和所有购物项的复选框长度一致的话就让总的复选框选中,否则则不会被选中allChecked.checked = allCheckNum === checks.length;//通过传入一个this对象进行求和,后面在这个函数里面会统一解决这个this对象getSumByCheck(this);//求总和getSum();}
}

以上问题解决的是点击购物项的按钮复选框就会监听当前对应的商店的总复选框下的所以购物项的复选框是否全部被选中,如果全部被选中,则将每个商店的总复选框选中

1.3.4 商店复选框选中的处理

商店复选框的处理也是也不是很难,大概也就是点击之后有个监听的效果,点击一次判断一次,某一个商店的复选框被选中后,他的购物项也会被选中,所有商店的复选框被选中后,总的复选框也会被选中

//获取到每一个商店的头复选框
let checkAll = document.querySelectorAll('.shop-name .check');
//获取总复选框
let allChecked = document.querySelector('#AllCheck');
//遍历每一个商店的头复选框
for (let i = 0; i < checkAll.length; i++) {//给每一个商店的头复选框绑定点击事件checkAll[i].onclick = function () {//先通过父节点寻找到外层的divlet item = checkAll[i].closest('.shop-group-item');//在通过外层的div找到ul下的所有复选框let check = item.querySelectorAll('.shop-group-item ul li .check');//遍历这个商店底下的所有复选框for (let j = 0; j < check.length; j++) {//如果这个商店下的所有复选框都被选中,那么这个商店的头复选框也被选中check[j].checked = this.checked;}//判断总的复选框按钮let num = 0;//遍历所有商店的头复选框for (let j = 0; j < checkAll.length; j++) {//判断头复选框是否被选中,如果被选中的话就让num+1if (checkAll[j].checked) {num += 1;}}//如果num和所有商店的头复选框数组长度一样的话,就返回true,然后总计按钮就是被选中的allChecked.checked = num === checkAll.length;//传入当前的对象,进行求和getSumByCheck(this);//求总和getSum();}
}

以上代码是解决了某一个商店的复选框被选中后,他的购物项也会被选中,所有商店的复选框被选中后,总的复选框也会被选中,并进行了求和,求和会在后面的代码中写出

1.3.5 总复选框的处理

总复选框实现的需求就是点击总复选框的时候,他会选择上面的所有复选框,上面所有复选框被选中的时候,总复选框也会被选中

实现的大概就是这样一个效果

//对总复选框进行绑定一个点击事件
allChecked.onclick = function () {//遍历除总复选框以外的所有复选框for (let i = 0; i < allCheck.length; i++) {//这里是如果总复选框被选中的话,那么所有复选框也会被选中allCheck[i].checked = this.checked;//下面的操作是为了当总复选框被选中后,计算每个商店的总计值,然后添加到每个商店的总计数量里面去//我本来想给他封装成一个方法的,因为之前的所有求和都是封装成方法了,但是这个this指向的问题,没有办法把这个和上面那些求和方法封装在一个方法里面//所以如果为了这一个计算而把他单拎出来封装成方法的话,没有太大的必要,所以就写在这个点击事件里面了//获取商店复选框的shop-group-item父节点let item = allCheck[i].closest('.shop-group-item');//然后通过父节点获取每一个商店下面的复选框,这里面是获取所有的除商店复选框以外的所有复选框//因为我们需要通过这个对象去获取当前购物项的价格和数量,并进行计算let check = item.querySelectorAll('.shop-info .check');//判断总的复选框是否被选中,被选中则进入计算,不被选中则不会进入计算if (this.checked) {//初始化每个商店的总价let totalCash = 0;//遍历for (let j = 0; j < check.length; j++) {//通过上面获取到的购物项的复选框去找每个购物项的价格let money = parseFloat(check[j].closest('.shop-info').querySelector('.price').innerText);//通过上面获取到的购物项的复选框去找每个购物项的数量let count = parseInt(check[j].closest('.shop-info').querySelector('.num').value);//判断购物项的复选框是否被选中,如果被选中则进入计算if (check[j].checked) {totalCash += money * count;}}//将总价添加到本店总计里面item.querySelector('.shopPrice .shop-total-amount').innerText = totalCash;}else {//如果总复选框没有被选中的话,则让所有的购物项的值都变成0item.querySelector('.shopPrice .shop-total-amount').innerText = 0;}}//求总价getSum();
}

以上求和方法我是单独拎出来求和的,这个选择可能不是很明智,因为它的代码和上面传参的求和函数的代码是差不多的,不过是传入的this指向有些问题,因为他们没有共同的父级元素,只有一个body,对于body操作就有点不大好了,所以我就把他单拎出来了,这是我目前能想到的唯一方法,大家有什么好的方法也可以多多提出

1.4 JS代码

window.onload = function () {/*计算value值*///获取减号按钮let minus = document.querySelectorAll('.shop-group-item .shop-info .shop-price .minus');//获取加号按钮let plus = document.querySelectorAll('.shop-group-item .shop-info .shop-price .plus');for (let i = 0; i < plus.length; i++) {/*加法的计算*/plus[i].onclick = function () {//通过点击的元素获取到value值let num = parseInt(this.parentElement.querySelector('.num').value);console.log(num);this.parentElement.querySelector('.num').value = num + 1;//获取到当前节点下的所有复选框getSumByCheck(this);getSum();}/*减法计算*/minus[i].onclick = function () {//通过点击的元素获取到value值let num = parseInt(this.parentElement.querySelector('.num').value);console.log(num);//判断如果num的最小值为0if (num > 0) {this.parentElement.querySelector('.num').value = num - 1;}//获取到当前节点下的所有复选框getSumByCheck(this);getSum();}}//获取到每一个商店的头复选框let checkAll = document.querySelectorAll('.shop-name .check');//获取总复选框let allChecked = document.querySelector('#AllCheck');//遍历每一个商店的头复选框for (let i = 0; i < checkAll.length; i++) {//给每一个商店的头复选框绑定点击事件checkAll[i].onclick = function () {//先通过父节点寻找到外层的divlet item = checkAll[i].closest('.shop-group-item');//在通过外层的div找到ul下的所有复选框let check = item.querySelectorAll('.shop-group-item ul li .check');//遍历这个商店底下的所有复选框for (let j = 0; j < check.length; j++) {//如果这个商店下的所有复选框都被选中,那么这个商店的头复选框也被选中check[j].checked = this.checked;}//判断总的复选框按钮let num = 0;//遍历所有商店的头复选框for (let j = 0; j < checkAll.length; j++) {//判断头复选框是否被选中,如果被选中的话就让num+1if (checkAll[j].checked) {num += 1;}}//如果num和所有商店的头复选框数组长度一样的话,就返回true,然后总计按钮就是被选中的allChecked.checked = num === checkAll.length;//传入当前的对象,进行求和getSumByCheck(this);//求总和getSum();}}//通过单个点击获取到所有,获取到所有的购物项let checks = document.querySelectorAll('.shop-group-item ul li .check');//遍历所有购物项,目的是给所有购物项里面的某一个购物项绑定点击事件,然后获取他的唯一父元素for (let i = 0; i < checks.length; i++) {//绑定点击事件,你点击哪一个,咱就能获取到哪一个的商店的头复选框checks[i].onclick = function () {//通过选中的复选框找到当前节点下itemlet item = this.closest('.shop-group-item');console.log(item);//再通过item来获取到当前节点下有多少个复选框let check = item.querySelectorAll('ul li .check');console.log(check.length);//通过item获取到当前节点下的总复选框let checkTotal = item.querySelector('.shop-name .check');console.log(checkTotal);//这里相当于是一个监听的效果,每点击一次,就会监听当前点击对象对应的父对象下面的子复选框是否全部被选中//说白了也就是判断当前点击元素平级的复选框是否全部被选中let checkNum = 0;for (let j = 0; j < check.length; j++) {//如果被选中一个,那么checkNum就会自动+1if (check[j].checked) {checkNum += 1;}}//如果当前点击元素平级的复选框被选中的值和该数组的长度一样的话,就让当前商店的头复选框选中checkTotal.checked = checkNum === check.length;//这里也相当于是一个监听的效果,每点击一次监听一下所有的购物项的复选框是否被选中let allCheckNum = 0;for (let j = 0; j < checks.length; j++) {//如果被选中的话就+1if (checks[j].checked) {allCheckNum += 1;}}console.log('allCheckNum:' + allCheckNum);//如果当前所有购物项被选中的复选框和所有购物项的复选框长度一致的话就让总的复选框选中,否则则不会被选中allChecked.checked = allCheckNum === checks.length;//通过传入一个this对象进行求和,后面在这个函数里面会统一解决这个this对象getSumByCheck(this);//求总和getSum();}}//通过点击总价获得选中所有复选框//获取除总复选框以外的所有复选框let allCheck = document.querySelectorAll('.shop-group-item .check');//对总复选框进行绑定一个点击事件allChecked.onclick = function () {//遍历除总复选框以外的所有复选框for (let i = 0; i < allCheck.length; i++) {//这里是如果总复选框被选中的话,那么所有复选框也会被选中allCheck[i].checked = this.checked;//下面的操作是为了当总复选框被选中后,计算每个商店的总计值,然后添加到每个商店的总计数量里面去//我本来想给他封装成一个方法的,因为之前的所有求和都是封装成方法了,但是这个this指向的问题,没有办法把这个和上面那些求和方法封装在一个方法里面//所以如果为了这一个计算而把他单拎出来封装成方法的话,没有太大的必要,所以就写在这个点击事件里面了//获取商店复选框的shop-group-item父节点let item = allCheck[i].closest('.shop-group-item');//然后通过父节点获取每一个商店下面的复选框,这里面是获取所有的除商店复选框以外的所有复选框//因为我们需要通过这个对象去获取当前购物项的价格和数量,并进行计算let check = item.querySelectorAll('.shop-info .check');//判断总的复选框是否被选中,被选中则进入计算,不被选中则不会进入计算if (this.checked) {//初始化每个商店的总价let totalCash = 0;//遍历for (let j = 0; j < check.length; j++) {//通过上面获取到的购物项的复选框去找每个购物项的价格let money = parseFloat(check[j].closest('.shop-info').querySelector('.price').innerText);//通过上面获取到的购物项的复选框去找每个购物项的数量let count = parseInt(check[j].closest('.shop-info').querySelector('.num').value);//判断购物项的复选框是否被选中,如果被选中则进入计算if (check[j].checked) {totalCash += money * count;}}//将总价添加到本店总计里面item.querySelector('.shopPrice .shop-total-amount').innerText = totalCash;}else {//如果总复选框没有被选中的话,则让所有的购物项的值都变成0item.querySelector('.shopPrice .shop-total-amount').innerText = 0;}}//求总价getSum();}/*总价求和*/function getSum() {//先获取每个infolet infos = document.querySelectorAll('.shop-group-item .shop-info');//设置总价格let totalCash = 0;for (let i = 0; i < infos.length; i++) {//再获取对应个info下面的价格let money = parseFloat(infos[i].querySelector('.price').innerText);//console.log(money);//获取对应info下面的value值let value = parseInt(infos[i].querySelector('.num').value);//console.log(value);//获取到复选框对象let check = infos[i].querySelector('.check');//如果被选中的话就进行计算if (check.checked) {totalCash += money * value;}/*infos[i].closest('.shop-group-item').querySelector('.shopPrice .shop-total-amount').innerText = totalCash;*/}document.querySelector('.payment-bar .total').innerText = totalCash;//将总价放在每一个总计标签里面}/*根据check子节点求和*/function getSumByCheck(_this) {//其实我们传过来的所有this对象他们都是有一个共同的父级,也就是shop-group-item这个div标签//上面有个对于总复选框进行判断的一个点击事件,之所以没有使用这个方法的原因是,他和shop-group-item这个div标签是平级的,所以无法获取到这个DOM对象,所以就把他单拎出来了let item = _this.closest('.shop-group-item');//获取到当前this对象对应的shop-group-item下的所有复选框let check = item.querySelectorAll('.shop-info .check');//初始化总价let totalCash = 0;//遍历求和for (let j = 0; j < check.length; j++) {//获取每一个的单价let money = parseFloat(check[j].closest('.shop-info').querySelector('.price').innerText);//获取每一个的数量let count = parseInt(check[j].closest('.shop-info').querySelector('.num').value);//判断是否被选中,被选中则进入计算if (check[j].checked) {totalCash += money * count;}}//将总价添加到本店总计里面item.querySelector('.shopPrice .shop-total-amount').innerText = totalCash;}
}

里面的注释其实挺全的,代码的每一步都有注释,大家看起来也方便

到这里基本所有的代码都写完了,其实也不是很多,逻辑也不是很复杂,就是一些细节处理方面可能比较麻烦。

1.5 CSS代码

base.css

@charset "utf-8";
html,body,div,p,form,label,ul,li,dl,dt,dd,ol,img,button,b,em,strong,small,h1,h2,h3,h4,h5,h6{margin:0;padding:0;border:0;list-style:none;font-style:normal;}
body{font-family:SimHei,'Helvetica Neue',Arial,'Droid Sans',sans-serif;font-size:14px;color:#333;background:#f2f2f2;}
a, a.link{color:#666;text-decoration:none;font-weight:500;}
a, a.link:hover{color:#666;}
h1,h2,h3,h4,h5,h6{font-weight: normal;}
/*头部开始*/
.header{position:relative;width:100%;height:44px;background:#fff;border-bottom:1px solid #e0e0e0;}
.header h1{font-size:16px;color:#333;height:44px;line-height:44px;display:block;text-align:center;}
.header a{position: absolute;top:0;display:block;height:44px;line-height:44px;}
.header a.back{left:0px;}
.header a.back span{display:inline-block;width:25px;height:25px;margin:10px 5px;background: url("../img/icon/icon-back.png") no-repeat;background-size:100%;}
.header .home{}
/*头部结束*/input[type="checkbox"]{-webkit-appearance:none;outline: none;}
input.check{background:url(../img/icon/icon_radio3.png) no-repeat center left;background-size:20px 20px;position:absolute;top:50%;left:10px;margin-top:-18px;width:20px;height:35px;}
input.check:checked{background:url(../img/icon/icon_radio4.png) no-repeat center left;background-size:20px 20px;}
input.goodsCheck:checked{background:url(../img/icon/icon_radio4.png) no-repeat center left;background-size:20px 20px;}
input.check:checked{background:url(../img/icon/icon_radio4.png) no-repeat center left;background-size:20px 20px;}
.checked{background:url(../img/icon/icon_radio4.png) no-repeat left center;background-size:20px 20px;position:absolute;top:50%;left:15px;margin-top:-18px;width:20px;height:35px;}/*尾部开始*/
.footer .copyright{height:44px;line-height:44px;text-align:center;color:#848689;font-size:12px;}
/*尾部结束*/

module.css

@charset "utf-8";
/* CSS Document */
/*购物车*/
.shopping{clear:both;overflow:hidden;height:auto;padding-bottom: 60px;}
.shop-group-item{margin-bottom:5px;}
.shop-group-item ul li{border-bottom:1px solid #fff;}
.shop-group-item ul li:last-child{border-bottom:none;}.shop-name{background:#fff;height:35px;line-height:35px;padding:0 15px;position:relative;}
.shop-name h4{float:left;font-size:14px;background:url(../img/icon/icon-kin.png) no-repeat left center;background-size:20px 20px;padding-left:25px;margin-left: 28px;}
.shop-name .coupons{float:right;}
.shop-name .coupons span{display:inline-block;padding:0 5px;}
.shop-name .coupons em{color:#e0e0e0;}.shop-info{background:#f5f5f5;height:120px;padding:0 15px;position:relative;}
.shop-info .checkbox{background:url(../img/icon/icon_radio3.png) no-repeat left center;background-size:20px 20px;position:absolute;top:50%;left:15px;margin-top:-60px;width:20px;height:120px;}
.shop-info .checkbox1{background:url(../img/icon/icon_radio4.png) no-repeat left center;background-size:20px 20px;position:absolute;top:50%;left:15px;margin-top:-60px;width:20px;height:120px;}
.shop-info .shop-info-img{position:absolute;top:15px;left:45px;width:90px;height:90px;}
.shop-info .shop-info-img img{width:100%;height:100%;}
.shop-info .shop-info-text{margin-left:130px;padding:15px 0;}
.shop-info .shop-info-text h4{font-size:14px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow: hidden;}
.shop-info .shop-info-text .shop-brief{height:25px;line-height:25px;font-size:12px;color:#81838e;white-space:nowrap;}
.shop-info .shop-info-text .shop-brief span{display:inline-block;margin-right:8px;}
.shop-info .shop-info-text .shop-price{height:24px;line-height:24px;position:relative;}
.shop-info .shop-info-text .shop-price .shop-pices {color:red;font-size:16px;}
.shop-info .shop-info-text .shop-arithmetic{position:absolute;right:0px;top:0;width:84px;box-sizing:border-box;white-space:nowrap;height:100%;border:1px solid #e0e0e0;}
.shop-info .shop-info-text .shop-arithmetic a{display:inline-block;width:23px;height:22px;line-height:22px;text-align:center;background:#fff;font-size:16px;}
.shop-info .shop-info-text .shop-arithmetic .minus{border-right:1px solid #e0e0e0;}
.shop-info .shop-info-text .shop-arithmetic .failed{color:#d1d1d1;}
.shop-info .shop-info-text .shop-arithmetic .plus{border-left:1px solid #e0e0e0;}
.shop-info .shop-info-text .shop-arithmetic .num{width:32px;text-align:center;border:none;display: inline-block;height:100%;box-sizing:border-box;vertical-align:top;margin:0 -6px;}
.shopPrice{background:#fff;height:35px;line-height:35px;padding:0 15px;text-align:right;}
.shopPrice span{color:#f00;}.payment-bar{clear:both;overflow:hidden;width:100%;height:49px;position:fixed;bottom:0;border-top:1px solid #e0e0e0;background:#fff;}
.payment-bar .all-checkbox{float:left;line-height:49px;padding-left:40px;}
.payment-bar .shop-total{float:left;-webkit-box-flex:1.0;box-flex:1.0;margin:9px 20px 9px 35px;}
.payment-bar .shop-total strong{display:block;font-size:16px;}
.payment-bar .shop-total span{display:block;font-size:12px;}
.payment-bar .settlement{display:inline-block;float:right;width:100px;height:49px;line-height:49px;text-align:center;color:#fff;font-size:16px;background:#f23030;}

这里面的样式和HTML结构都不是我写的,我只写了JS的代码,大家有需要可以自提,然后练习对DOM对象的操作

二. 总结

以上便是这篇博文的全部内容,主要内容就是对购物车案例升级的编写,和上一篇写的不同点在于,这篇博文将购物车里面进行了分类处理,分类处理每一个商店里面的每一个购物项,主要难点在于对DOM对象的操作,调用父级DOM对象和通过父级的DOM对象再次调用子级的DOM对象,相当于是一个DOM树之间的互相调用的处理方式,这两天的博客都是一些案例,案例主要练习的也就是对JavaScript中DOM对象的操作练习。

以上就是全部内容,我只写了JS代码,HTML和CSS都是案例的提供的文件,有时间的话我也会尝试着将整个案例完整的写下来,以上JS代码中,对于逻辑的处理是我目前想到的还不错的写法,可能代码中还会存在着一些没有发现的问题,大家看了之后发现有什么错误,或者看完之后有什么更好的想法也可以多多提出,大家一起学习,共同进步!!!

前端学习——JavaScript原生实现购物车案例相关推荐

  1. 前端学习——JavaScript抽屉,手风琴,购物车特效案例

    一. JavaScript案例介绍 这篇我们通过一些JavaScript案例来完成对JavaScript中BOM对象和DOM对象的理解 首先我们会学到三种常用的JavaScript案例特效 分别是 手 ...

  2. javascript+css+html购物车案例

    javascript代码部分主要实现三部分功能 1.商品数量增加(减少)同时小计增加(减少) 这部分主要是通过for循环给增加(减少)按钮绑定点击事件 1)点击后计数器自增(自减) 2)计数器数量*对 ...

  3. 前端学习-JavaScript基础(正则表达式)

    正则表达式 正则表达式在很多程序设计语言都有,大同小异,尤其是在Python爬虫的使用很多,我也就跟他们学习爬爬图片,小视频啥的,咳咳都是学习资料.在JavaScript中,使用比较多的是表单验证,字 ...

  4. 前端学习-JavaScript基础

    一.初识JavaScript 官网: https://www.w3.org/standards/webdesign/script 说明: JavaScript语法规范是ECMAScript,ECMAS ...

  5. 前端学习—JavaScript

    文章目录 JavaScript 1.引入JavaScript 2.基本语法 3.数据类型 字符串类型 数组 对象 流程控制 Map和Set 严格模式 4.函数 定义函数 5.函数的作用域 6.方法 7 ...

  6. 前端学习-JavaScript基础(ES6)

    简介: ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版. ES6 主要是为了解决 ES5 的先天不足,比如 JavaScript 里并 ...

  7. 前端学习----JavaScript

    目录 day  one 1.1,JavaScrip-脚本语言 1.2,输出 1.3,应用举例 1.4,基础了解 1.5,数据类型 1.6,类型转换 1.7,运算符 1.8,流程控制语句 Day  tw ...

  8. 前端学习JavaScript基础阶段

    初识javascript JavaScript介绍 是一种运行在客户端(浏览器)的编程语言,实现人机交互效果.作用: 网页特效 表单验证 数据交互 服务端编程(node.js)组成: ECMAScri ...

  9. 前端学习当中的一些js案例

    标题 js案例 ** 三目运算符求四个数中的最大值(使用js 和c 的实现) ** 找找感觉 #include<stdio.h>void main() {float a,b,c,d;flo ...

最新文章

  1. 华为将发布世界首款人工智能原生数据库
  2. 【struts2】struts2中对象的获取
  3. 启动web项目(maven)
  4. impdp oracle 只导入表结构_oracle数据库怎么导入dmp,只导入数据不导入表结构?...
  5. PostgreSQL-13-缺失值处理
  6. CANoe——CAPL
  7. linux下查看设备的接口,linux 查看sdio接口有哪些设备?
  8. [内附完整源码和文档] 基于MySql和JSP的题库管理系统
  9. 各大IT公司经典面试题总结
  10. Word、WPS 文字背景颜色无法去除
  11. TMT/MOBIE成像光谱仪的概念设计阶段杂散光分析
  12. 计算机操作系统-文件管理 知识点归纳
  13. uni-app的学习之路
  14. 数据采集的方法有哪些
  15. java web 编辑器_22个所见即所得在线 Web 编辑器
  16. 【长难句分析精讲】并列结构
  17. µTorrent中只使用ipv6连接
  18. JavaScript函数的使用以及下拉框、文本框、radio值的获取,结合一个淘宝竞价案例。。。
  19. 月薪5w的大佬都爱用的SWOT分析法,本文分析透了!
  20. 如何使用Vue.js中的set设置对象属性值

热门文章

  1. 【花雕】全国青少年机器人技术一级考试备考实操搭建手册2
  2. 喜讯丨星舆科技连续四年入选“全国科技型中小企业”
  3. 快递100发货模板代码,发货前订阅消息推送,发货后直接更新最新物流信息
  4. 白帽子漏洞提交众测平台(网站链接)
  5. 软件开发必知必会的计算机基础
  6. easy一个极为简单的程序(1)
  7. Ansible 1.5.9:archive 模块
  8. 2017年“嘉杰信息杯” 中国大学生程序设计竞赛全国邀请赛(湖南) 暨 第九届湘潭市大学生程序设计比赛H.Highway(树的直径)
  9. 论道5G+AI的新未来!5G未来沙龙将于15日下午举办
  10. 四面阿里巴巴回来分享面经总结,定级P7架构师