【电商项目实战】购物车完善

🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的专栏《电商项目实战》。🎯🎯

👉点击这里,就可以查看我的主页啦!👇👇

Java方文山的个人主页

🎁如果感觉还不错的话请给我点赞吧!🎁🎁

💖期待你的加入,一起学习,一起进步!💖💖

请添加图片描述

前言 

我们已经完成了将数据加入购物车,这篇文章主要完善购物车页面的功能,比如:修改购物车的数量、全选、全不选、总价计算、小计计算等,话不多说上代码。

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">继续购物&gt;</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>合计:&nbsp;<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.删除商品

  1. 如果点击的是单个删除按钮,即父级元素的父级元素包含.th类,那么会弹出一个确认框,询问用户是否要删除该项。如果用户点击确认按钮(.cer类),则执行以下操作:

    • 隐藏蒙层(.mask类)和确认框(.tipDel类)。
    • 删除对应的.th元素。
    • 解绑.cer类的点击事件处理函数。
    • 检查剩下的.th元素数量,如果没有了,则显示提示信息(.goOn类)。
  2. 如果点击的是多个一起删除按钮,即选中了多个复选框(.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")//拿到商品idlet 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")@ResponseBodypublic 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);
@Overridepublic 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);}}

 效果演示:

请添加图片描述

到这里我的分享就结束了,欢迎到评论区探讨交流!!

💖如果觉得有用的话还请点个赞吧 💖

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/315620.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CharRNN实现简单的文本生成

文本数字表示 统计文档中的字符&#xff0c;并且统计字符个数。这里是为了将文字转换为数字表示。 import numpy as np import re import torch class TextConverter(object):def __init__(self,text_path,max_vocab5000):"""建立一个字符索引转换,主要还是为…

C++初阶------------------入门C++

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

生信技能32 - 导入UCSC公共数据库SNP数据至本地MySQL数据库

本文以导入SNP151.txt数据库为例,其他数据库文件操作类似。 1. 数据文件下载 UCSC下载网址: https://hgdownload.cse.ucsc.edu/goldenPath/hg19/database/ 以下为Linux下载文件方式 wget https://hgdownload.cse.ucsc.edu/goldenPath/hg19/database/snp151.sql wget -c -…

vue保姆级教程----深入了解 Vue Router的工作原理

&#x1f4e2; 鸿蒙专栏&#xff1a;想学鸿蒙的&#xff0c;冲 &#x1f4e2; C语言专栏&#xff1a;想学C语言的&#xff0c;冲 &#x1f4e2; VUE专栏&#xff1a;想学VUE的&#xff0c;冲这里 &#x1f4e2; CSS专栏&#xff1a;想学CSS的&#xff0c;冲这里 &#x1f4…

集合高级知识点

集合高级 1. HashSet 底层原理 HashSet 的特点&#xff1a; HashSet 实现了 Set 接口HashSet 底层实质上是 HashMap可以存放 null 值&#xff0c;但是只能有一个 nullHashSet 不保证元素是有序的&#xff0c;取决于 hash 后&#xff0c;再确定索引的结果&#xff0c;即不保证…

webRTC实时通信demo

参考文档&#xff1a; https://www.jianshu.com/p/f439ce5cc0be https://www.w3cschool.cn/socket demo流程示意图&#xff08;用户A向用户B推送视频&#xff09;&#xff1a; #mermaid-svg-0KZaDQ5DBl28zjmZ {font-family:"trebuchet ms",verdana,arial,sans-seri…

C++ STL set用法详解

我们都知道&#xff0c;set是STL里的一种数据结构&#xff0c;这篇博客就是set用法的详解。 1.set的创建。 set初始化一般是 set<数据结构名称> 名字; 具体例子&#xff1a; 创建一个int型&#xff0c;名称是s的set。 set<int> s; set还可以创建STL里的数据…

深入剖析ShardingSphere:探索其内核原理与核心源码,揭秘分库分表技术的奥秘

一、 内核剖析 ShardingSphere虽然有多个产品&#xff0c;但是他们的数据分片主要流程是完全一致的。 解析引擎 解析过程分为词法解析和语法解析。 词法解析器用于将SQL 拆解为不可再分的原 子符号&#xff0c;称为Token。 并根据不同数据库方言所提供的字典&#xff0c;将其…

Linux操作系统极速入门[常用指令]

linux概述&#xff1a; Linux是一套免费使用和自由传播的操作系统 我们为什么要学&#xff0c;Linux&#xff1f; 主流操作系统&#xff1a; linux系统版本&#xff1a; 内核版&#xff1a; 由linux核心团队开发&#xff0c;维护 免费&#xff0c;开源 负责控制硬件 发行版&…

瑞典最大的连锁超市Coop再遭勒索软件团伙攻击

近日&#xff0c;仙人掌勒索软件团伙声称已经黑入了瑞典最大的连锁超市Coop&#xff0c;并威胁要公开大量个人信息&#xff0c;超过2万个目录。 据了解&#xff0c;Coop在瑞典大约有800家商店&#xff0c;这些商店分属于29个消费者协会&#xff0c;拥有350万个会员&#xff0c…

drf知识-09

自定义频率类 # throttling 频率限制 # 简单方案 from rest_framework.throttling import SimpleRateThrottle class CommonThrottle(SimpleRateThrottle):rate 3/mdef get_cache_key(self, request, view):ip request.META.get(REMOTE_ADDR)return ip# 复杂方案---》通用方案…

灰度发布及声明式资源管理(yaml文件)

一、三种常见的项目发布方式 1&#xff09;蓝绿发布 2&#xff09;灰度发布【常用】 3&#xff09;滚动发布 应用程序升级&#xff0c;面临最大的问题是新旧业务之间的切换 立项-定稿-需求发布-开发-测试-发布&#xff0c;测试上线后&#xff0c;再完美也会有问题&#xff0c;为…