【电商项目实战】购物车完善
🎉🎉欢迎来到我的CSDN主页!🎉🎉
🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚
🌟推荐给大家我的专栏《电商项目实战》。🎯🎯
👉点击这里,就可以查看我的主页啦!👇👇
🎁如果感觉还不错的话请给我点赞吧!🎁🎁
💖期待你的加入,一起学习,一起进步!💖💖
前言?
我们已经完成了将数据加入购物车,这篇文章主要完善购物车页面的功能,比如:修改购物车的数量、全选、全不选、总价计算、小计计算等,话不多说上代码。
cart.html(页面代码)
<!DOCTYPE html>
<html>
<head lang="en">
<#include "common/head.html">
<link rel="stylesheet" type="text/css" href="css/public.css"/>
<link rel="stylesheet" type="text/css" href="css/proList.css" />
</head>
<body onload="jisuan()">
<!--------------------------------------cart--------------------->
<div class="head ding">
<div class="wrapper clearfix">
<div class="clearfix" id="top">
<h1 class="fl"><a href="${ctx}/"><img src="img/logo.png"/></a></h1>
<div class="fr clearfix" id="top1">
<form action="#" method="get" class="fl">
<input type="text" placeholder="搜索" />
<input type="button" />
</form>
</div>
</div>
</div>
</div>
<div class="cart mt">
<!-----------------logo------------------->
<!--<div class="logo">
<h1 class="wrapper clearfix">
<a href="${ctx}/"><img class="fl" src="img/temp/logo.png"></a>
<img class="top" src="img/temp/cartTop01.png">
</h1>
</div>-->
<!-----------------site------------------->
<div class="site">
<p class=" wrapper clearfix">
<span class="fl">购物车</span>
<img class="top" src="img/temp/cartTop01.png">
<a href="${ctx}/" class="fr">继续购物></a>
</p>
</div>
<!-----------------table------------------->
<div class="table wrapper">
<div class="tr">
<div>商品</div>
<div>单价</div>
<div>数量</div>
<div>小计</div>
<div>操作</div>
</div>
<#--有数据就显示-->
<#if item??>
<#list item as g>
<div class="th">
<div class="pro clearfix">
<label class="fl">
<input type="checkbox" data-gid="${g.gid}"/>
<span></span>
</label>
<a class="fl" href="#">
<dl class="clearfix">
<dt class="fl"><img src="${(g.goodsImg)!}" style="width: 100px;height: 100px"></dt>
<dd class="fl">
<p>${(g.goodsName)!}</p>
<p>颜色分类:</p>
<p>${(g.goodsType)!}</p>
</dd>
</dl>
</a>
</div>
<div class="price myprice">¥${(g.goodsPrice)!}</div>
<div class="number">
<p class="num clearfix">
<img class="fl sub" src="img/temp/sub.jpg">
<span class="fl mycount" data-gid="${(g.gid)!}">${(g.num)!}</span>
<img class="fl add" src="img/temp/add.jpg">
</p>
</div>
<div class="price sAll">¥${(g.goodsPrice*g.num)!}</div>
<div class="price"><a class="del" data-gid="${g.gid}">删除</a></div>
</div>
</#list>
<#else>
<div class="goOn">空空如也~<a href="${ctx}/">去逛逛</a></div>
</#if>
<div class="tr clearfix">
<label class="fl">
<input class="checkAll" type="checkbox"/>
<span></span>
</label>
<p class="fl">
<a href="javascript:void(0);">全选</a>
<a href="javascript:void(0);" class="del">删除</a>
</p>
<p class="fr">
<span>共<small id="sl">0</small>件商品</span>
<span>合计: <small id="all">¥0.00</small></span>
<a class="count">结算</a>
</p>
</div>
</div>
</div>
<div class="mask"></div>
<div class="tipDel">
<p>确定要删除该商品吗?</p>
<p class="clearfix">
<a class="fl cer" href="javascript:void(0);">确定</a>
<a class="fr cancel" href="javascript:void(0);">取消</a>
</p>
</div>
<!--返回顶部-->
<#include "common/footer.html">
<!----------------mask------------------->
<div class="mask"></div>
<!-------------------mask内容------------------->
<div class="proDets">
<img class="off" src="img/temp/off.jpg" />
<div class="proCon clearfix">
<div class="proImg fr">
<img class="list" src="img/temp/proDet.jpg" />
<div class="smallImg clearfix">
<img src="img/temp/proDet01.jpg" data-src="img/temp/proDet01_big.jpg">
<img src="img/temp/proDet02.jpg" data-src="img/temp/proDet02_big.jpg">
<img src="img/temp/proDet03.jpg" data-src="img/temp/proDet03_big.jpg">
<img src="img/temp/proDet04.jpg" data-src="img/temp/proDet04_big.jpg">
</div>
</div>
<div class="fl">
<div class="proIntro change">
<p>颜色分类</p>
<div class="smallImg clearfix">
<p class="fl on"><img src="img/temp/prosmall01.jpg" alt="白瓷花瓶+20支快乐花" data-src="img/temp/proBig01.jpg"></p>
<p class="fl"><img src="img/temp/prosmall02.jpg" alt="白瓷花瓶+20支兔尾巴草" data-src="img/temp/proBig02.jpg"></p>
<p class="fl"><img src="img/temp/prosmall03.jpg" alt="20支快乐花" data-src="img/temp/proBig03.jpg"></p>
<p class="fl"><img src="img/temp/prosmall04.jpg" alt="20支兔尾巴草" data-src="img/temp/proBig04.jpg"></p>
</div>
</div>
<div class="changeBtn clearfix">
<a href="#2" class="fl"><p class="buy">确认</p></a>
<a href="#2" class="fr"><p class="cart">取消</p></a>
</div>
</div>
</div>
</div>
<div class="pleaseC">
<p>请选择宝贝</p>
<img class="off" src="img/temp/off.jpg" />
</div>
<script src="js/public.js" type="text/javascript" charset="utf-8"></script>
<script src="js/pro.js" type="text/javascript" charset="utf-8"></script>
<script src="js/cart.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
一、购物车功能完善(前端)
前面说到,我们cart.html的js代码都是移到cart.js里面的显示代码与功能代码区分开来,我们就直接在js里面写方法即可。
1.计算选中商品
- 首先定义了变量
zsl
用来保存选中的复选框对应的数量,初始化为0。 - 然后通过选择器找到所有被选中的复选框的父元素
.th
,再在父元素中找到.num span
元素,即数量显示的元素。 - 如果找到的数量为0,则将显示数量的元素
#sl
的文本设置为0。 - 否则,遍历每个数量显示的元素,将其文本转换为整数并累加到
zsl
上,并将最终的结果设置为#sl
的文本。 - 最后判断
#sl
的文本是否大于0,如果是,则将.count
元素的背景颜色设为红色#c10000
,否则设为灰色#8e8e8e
。
function zg(){
var zsl = 0;
var index = $(".th input[type='checkbox']:checked").parents(".th").find(".num span");
var len =index.length;
if(len==0){
$("#sl").text(0);
}else{
index.each(function(){
zsl+=parseInt($(this).text());
$("#sl").text(zsl);
})
}
if($("#sl").text()>0){
$(".count").css("background","#c10000");
}else{
$(".count").css("background","#8e8e8e");
}
}
效果演示:
2.计算总价和小计?
- 首先定义了变量
all
用来保存选中的复选框对应的小计金额的累加值,初始化为0。 - 然后通过选择器获取所有被选中的复选框的数量。
- 如果选中的复选框数量为0,则将显示总金额的元素
#all
的文本设置为¥0.00。 - 否则,遍历每个被选中的复选框,对应的执行以下操作:
- 获取该复选框所在父元素
.pro
的同级元素.sAll
的文本内容,即小计金额(去除¥符号)。 - 将小计金额转换为浮点数并累加到
all
上。 - 更新显示总金额的元素
#all
的文本为¥加上累加的金额,并保留两位小数。
- 获取该复选框所在父元素
function jisuan(){
//计算总价
var all=0;
var len =$(".th input[type='checkbox']:checked").length;
if(len==0){
$("#all").text('¥'+parseFloat(0).toFixed(2));
}else{
$(".th input[type='checkbox']:checked").each(function(){
//获取小计里的数值
var sAll = $(this).parents(".pro").siblings('.sAll').text().substring(1);
//累加
all+=parseFloat(sAll);
//赋值
$("#all").text('¥'+all.toFixed(2));
})
}
//计算小计
$(".th").each((i,el)=>{
//获得th中的价格
let price=$(el).find('.myprice').text().replace("¥","")*1
//获得th中的数量
let count=$(el).find('.mycount').text()*1
//放入小计
$(el).find('.sAll').text(price*count)
})
}
效果演示:
3.商品全选?
- 当单击一个复选框时,判断该复选框是否被选中以及是否具有
checkAll
类名。 - 如果当前复选框被选中且具有
checkAll
类名,则将所有复选框都设置为选中状态,并调用zg()
和jisuan()
函数。 - 如果当前复选框被选中但没有
checkAll
类名,则将当前复选框设置为选中状态,如果所有复选框都被选中,则将所有复选框都设置为选中状态,并调用zg()
和jisuan()
函数。 - 如果当前复选框未选中且具有
checkAll
类名,则将所有复选框都设置为未选中状态,并调用zg()
和jisuan()
函数。 - 如果当前复选框未选中且没有
checkAll
类名,则将当前复选框设置为未选中状态,如果当前选中的复选框数量小于所有复选框数量,则将全选复选框设置为未选中状态,并调用zg()
和jisuan()
函数。
$("input[type='checkbox']").on('click',function(){
var sf = $(this).is(":checked");
var sc= $(this).hasClass("checkAll");
if(sf){
if(sc){
$("input[type='checkbox']").each(function(){
this.checked=true;
});
zg();
jisuan();
}else{
$(this).checked=true;
var len = $("input[type='checkbox']:checked").length;
var len1 = $("input").length-1;
if(len==len1){
$("input[type='checkbox']").each(function(){
this.checked=true;
});
}
zg();
jisuan();
}
}else{
if(sc){
$("input[type='checkbox']").each(function(){
this.checked=false;
});
zg();
jisuan();
}else{
$(this).checked=false;
var len = $(".th input[type='checkbox']:checked").length;
var len1 = $("input").length-1;
if(len<len1){
$('.checkAll').attr("checked",false);
}
zg();
jisuan();
}
}
});
效果演示:?
4.数量加减
- 首先,
parseInt($(this).siblings("span").text())
用于获取当前点击按钮所在元素的兄弟元素中的文本内容,并将其转换为整数类型,得到商品的数量。 - 接着,通过判断数量是否小于等于1来决定是否禁用减号按钮。
- 如果数量大于1,将数量减1,并更新显示数量的元素的文本内容为新的数量。
- 然后,通过一系列DOM操作找到当前商品所在的行元素,并获取该行元素上的单价文本内容(去除货币符号)。
- 将单价和数量相乘,并使用
.toFixed(2)
方法保留两位小数,更新显示小计金额的元素的文本内容。 - 最后,调用
jisuan()
和zg()
函数,这两个函数可能是其他计算或处理代码。
$(".num .sub").click(function(){
var num = parseInt($(this).siblings("span").text());
if(num<=1){
$(this).attr("disabled","disabled");
}else{
num--;
$(this).siblings("span").text(num);
//获取除了货币符号以外的数字
var price = $(this).parents(".number").prev().text().substring(1);
//单价和数量相乘并保留两位小数
$(this).parents(".th").find(".sAll").text('¥'+(num*price).toFixed(2));
jisuan();
zg();
}
});
$(".num .add").click(function(){
var num = parseInt($(this).siblings("span").text());
if(num>=5){
confirm("限购5件");
}else{
num++;
$(this).siblings("span").text(num);
var price = $(this).parents(".number").prev().text().substring(1);
$(this).parents(".th").find(".sAll").text('¥'+(num*price).toFixed(2));
jisuan();
zg();
}
});
效果演示:
5.删除商品
-
如果点击的是单个删除按钮,即父级元素的父级元素包含
.th
类,那么会弹出一个确认框,询问用户是否要删除该项。如果用户点击确认按钮(.cer
类),则执行以下操作:- 隐藏蒙层(
.mask
类)和确认框(.tipDel
类)。 - 删除对应的
.th
元素。 - 解绑
.cer
类的点击事件处理函数。 - 检查剩下的
.th
元素数量,如果没有了,则显示提示信息(.goOn
类)。
- 隐藏蒙层(
-
如果点击的是多个一起删除按钮,即选中了多个复选框(
.th input[type='checkbox']:checked
),那么也会弹出一个确认框,询问用户是否要删除选中的项。如果用户点击确认按钮(.cer
类),则执行以下操作:- 遍历每一个被选中的复选框元素,获取它们对应的父级的父级元素索引(
.th
元素的索引)。 - 根据索引删除相应的
.th
元素。 - 检查剩下的
.th
元素数量,如果没有了,则显示提示信息(.goOn
类)。 - 隐藏蒙层(
.mask
类)和确认框(.tipDel
类)。 - 更新一些相关信息,可能是执行
zg()
和jisuan()
方法。
- 遍历每一个被选中的复选框元素,获取它们对应的父级的父级元素索引(
$('.del').click(function(){
//单个删除
if($(this).parent().parent().hasClass("th")){
$(".mask").show();
$(".tipDel").show();
index = $(this).parents(".th").index()-1;
$('.cer').click(function(){
$(".mask").hide();
$(".tipDel").hide();
$(".th").eq(index).remove();
$('.cer').off('click');
if($(".th").length==0){
$(".table .goOn").show();
}
})
}else{
//选中多个一起删除
if($(".th input[type='checkbox']:checked").length==0){
$(".mask").show();
$(".pleaseC").show();
}
else{
$(".mask").show();
$(".tipDel").show();
$('.cer').click(function(){
$(".th input[type='checkbox']:checked").each(function(j){
index = $(this).parents('.th').index()-1;
$(".th").eq(index).remove();
if($(".th").length==0){
$(".table .goOn").show();
}
})
$(".mask").hide();
$(".tipDel").hide();
zg();
jisuan();
})
}
}
})
二、购物车功能完善(后端)
?我们功能肯定不能只有前端发生变化,后端也需要做相应的操作,否则下次进来还是和之前一样
1.修改商品数量
为了明确我们拿到的是我们所选的商品,先在每个商品数量的span标签上加一个属性
<span class="fl mycount" data-gid="${(g.gid)!}">${(g.num)!}</span>
?随后编写我们的修改商品数量的函数
function update (el,count){
//获取该元素
let dom=$(".mycount")
//拿到商品id
let gid=dom.attr("data-gid")
let num=count
//将数量发送到后端
$.post('/cart/update',{num,gid},resp=>{
if(resp.code==200){
alert("修改数量成功")
}
},"json")
}
这里我们只需要在加减函数中调用该方法即可,该函数中的修改数量弹窗可以删除方便用户体验,我这里先写上,方便展示我这段代码确实过了数据库。
效果演示:
2.删除商品
我们首先需要在复选框上和删除上加上“data-gid”的属性
随后在我们商品的js中添加几行代码即可
$('.del').click(function(){
//不论删除单个还是多个都要保存到该集合
let ids=[];
//获取单条数据上面的gid属性
let gid=$(this).attr('data-gid');
ids.push(gid)
//单个删除
if($(this).parent().parent().hasClass("th")){
$(".mask").show();
$(".tipDel").show();
index = $(this).parents(".th").index()-1;
$('.cer').click(function(){
$(".mask").hide();
$(".tipDel").hide();
$(".th").eq(index).remove();
$('.cer').off('click');
if($(".th").length==0){
$(".table .goOn").show();
}
// 判断ids有无值
if(ids.length>0){
//将数量发送到后端
$.post('/cart/del',{ids},resp=>{
if(resp.code==200){
alert("删除成功")
location.href="http://localhost:8080/cart/getCart"
}
},"json")
}
})
}else{
//选中多个一起删除
if($(".th input[type='checkbox']:checked").length==0){
$(".mask").show();
$(".pleaseC").show();
}
else{
$(".mask").show();
$(".tipDel").show();
$('.cer').click(function(){
$(".th input[type='checkbox']:checked").each(function(j){
//获取单条数据上面的gid属性
let gid=$(this).attr('data-gid');
ids.push(gid)
index = $(this).parents('.th').index()-1;
$(".th").eq(index).remove();
if($(".th").length==0){
$(".table .goOn").show();
}
})
$(".mask").hide();
$(".tipDel").hide();
zg();
jisuan();
//判断ids有无值
if(ids.length>0){
//将数量发送到后端
$.post('/cart/del',{ids},resp=>{
if(resp.code==200){
alert("删除成功")
location.href="http://localhost:8080/cart/getCart"
}
},"json")
}
})
}
}
})
?后端controller代码
@RequestMapping("/del")
@ResponseBody
public JsonResponseBody<?> delete(@RequestParam("ids[]") List<String> ids, User user) {
//存储用户购物车信息
redisService.deleteCart(user, ids);
return JsonResponseBody.success();
}
service和impl代码
void deleteCart(User user, List<String> ids);
@Override
public void deleteCart(User user, List<String> ids) {
HashOperations<String,String,GoodsVo> operations=redisTemplate.opsForHash();
String bigKey=Constants.REDIS_CART_PREFIX + user.getId();
for (String id : ids) {
operations.delete(bigKey,id);
}
}
?效果演示:
?
到这里我的分享就结束了,欢迎到评论区探讨交流!!
💖如果觉得有用的话还请点个赞吧 💖
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!