购物车-前后端分离版
前言
看了很多网上关于购物车的内容,感觉没一个可以用的。现在用到购物车的场景太多了,各种APP,小程序,网站都有。
先说一下前后端分离问题。
在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高。这种应用模式比较适合纯网页应用,但是当后端对接App时,App可能并不需要后端返回一个HTML网页,而仅仅是数据本身,所以后端原本返回网页的接口不再适用于前端App应用,为了对接App后端还需再开发一套接口。
在前后端分离的应用模式中,后端仅返回前端所需的数据,不再渲染HTML页面,不再控制前端的效果。至于前端用户看到什么效果,从后端请求的数据如何加载到前端中,都由前端自己决定,网页有网页的处理方式,App有App的处理方式,但无论哪种前端,所需的数据基本相同,后端仅需开发一套逻辑对外提供数据即可。
思路
购物车与前端的交互,完全是JSON交互。在做购物车这个功能之前,先用 Fiddler 4(不会用自己百度) 抓包工具看下现在大厂的应用是怎么做的
小米商城 | 购物车的商品信息计算在前端,比如点击了购物车里面的数量 + 和 - 都是不调用后端接口,直接客户端计算了购物车的商品价格。 |
京东商城 | 完全依赖后端返回的数据,每一次 + 和 - 都是后端计算,并且将整个购物车计算结果返回。 |
淘宝 | 淘宝我没仔细看,不过比较有意思的是淘宝在商品加入购物车的页面居然不显示购物车商品的总数。 |
我最赞成京东商城的做法,完全依赖后端计算,因为京东的店铺系统是最复杂的,有自己的店,也有第三方旗舰店,也有跨店满减以及PLUS会员价格不一样等等,这些规则,显然不能前端来计算,甚至购物车里面十几个商品中每一个商品是否被选中都影响到计算总价的。
你可能会说,你的业务可能不会像京东那么复杂,可以前端直接根据商品数量计算价格,考虑后续,比如你们系统后续不会做促销,梯度价格(买1个还是3个价格可能不一样哦)等。甚至你们公司现在只卖自己的商品,后续别的商家跟你们合作,在你们的网站上卖,不就是第三方旗舰店吗?这个时候需要可以变得分组,就是商家分组,每个商家会有不同的包邮费呢。
综上,数据完全依赖后端,前端只做好展示的架构就OK啦。
前端交互数据设计
在接口设计之前,先要看一下基本购物车的整体数据结构。
{"money": 3400, //购物车总价"selMoney": 3400, //选中商品总价 "num": 2, //购物车商品总数"infoSelectStatus": 1, //整个购物车是否全选"busList": [ {"businessId": "1", //商家id,自营的1"businessName": "XX自营", //商家名称"freeShipping": "满99包邮", //商家包邮策略"businessSelectStatus": 1, //商家分组的商品是否全选"proList": [{"productCode": 2983, //商品code"productName": "天麻素胶囊", //商品名称"classCode": "010502", //商品分类"unit": "盒", //计量单位"manufacturer": "广东邦民制药厂有限公司","packing": "50mg*10s", "marketPrice": 388, //市场价(划线价)"ourPrice": 379, //购买价"img100": "/upload/prodimage/201604_100/2016413163328132.jpg","merchantManageCode": "1", //商家ID "merchantName": "XX自营", //商家名称 "maxNum": 200, //限购数量"productNum": 1, //商品数量"selectStatus": 1, //商品选中状态"productStatusOrderBy": 1 //是否下架}]}]
}
这是一个基本的数据结构,总体->商家组->商品组。
比这个再复杂的结构也是在这个基础上的变种,比如加一个“离包邮差XX元”,这个可是放在商家的分组上,不同商家分开发货哦,自营是一个分组。甚至还可以再加一个跨店满减分组,包在商家分组上面,看几个商家的总价。
总体->跨店满减组->商家组->商品组。这里跨店满减组与商家组在客户端可以平级显示,需要特殊处理,对分组做一个优先级显示,可以先不管。
再复杂点,每个商品会有赠品,就是 总体->跨店满减组->商家组->商品组->赠品组。
我们这次只搞明白我给出的代码中的购物车就OK啦。
交互接口设计
接口设计如下表所示(参数)
序号 | 接口含义 | 接口定义 | 接口参数 | 返回值 |
---|---|---|---|---|
1 | 查购物车详情 | getCartInfo | userId | cart(上图中的购物车json) |
2 | 查单个商品数量 | getProductNum | userId,productCode | productNum(商品数量) |
3 | 查看购物车商品总数 | getAllNum | userId | allNum(商品总数) |
4 | 向购物车加商品 | addProductToCart | userId,productCode,productNum | allNum(商品总数) |
5 | 批量删购物车商品 | deleteCartProduct | userId,productCodeList(多个商品) | cart(上图中的购物车json) |
6 | 清空购物车 | cleanCart | userId | 返回空就行,前端根据接口是否调成功,在前端清空购物车 |
7 | 更新商品数量( + 和 - 也调用这个接口) | updateCartProductNum | userId,productCode,productNum | cart(上图中的购物车json) |
8 | 再次购买 | buyAgain | userId,orderId | 空 |
9 | 修改单个商品选中状态 | changeSelectStatusProduct | userId,productCode,selectStatus | cart(上图中的购物车json) |
10 | 修个组选中状态(每个商家分组或者活动分组) | changeSelectStatusBusiness | userId,businessId,selectStatus | cart(上图中的购物车json) |
11 | 修改购物车全选状态 | changeSelectStatusAll | userId,selectStatus | cart(上图中的购物车json) |
参数说明:userId可以放在头信息里面,每个接口都不用传,如果是同一公司的系统多个应用共用购物车接口,可以多传一个客户端类型,按照不同应用(比如,淘宝,天猫共用一套购物车接口)区分,在部分电商系统有“渠道”的说法,不同应用不同“渠道”,甚至不同用户在不同应用都是有不同“渠道”的,这个参数也可以放在头信息里。
上面接口中大致分为两种,第一种是在购物车页面中操作的接口,另一种是不在购物车操作的接口。
不在购物车页面操作的接口有:第4个,向购物车加商品是在浏览商品时添加,返回一个购物车商品总数,京东是返回的商品种类数量,淘宝是直接不显示商品数。第8个再次购买是在订单页面操作,将订单的商品再一次加入到购物车之中,不需返回购物车信息。其他在购物车的操作,统一返回整个购物车JSON,后端需要重新计算总价和分组总价,某一个商品是否选中可能都涉及到不同的优惠价格。
第2个接口,第6个接口使用场景不多,可以不做。
后端数据设计
有了以上的基础,再看后端的数据是否有了一点眉目,后端的设计可能每家在细节会有所不同,但是整体架构不会变。数据分为两部分,一部分是购物车数据,一部分是商品详情数据,购物车不存任何商品详情,只存商品code。因为商品可能会变,比如价格,介绍,图片链接等等,所以前端接收的购物车的数据,后端做了组合后返回给前端的。
这个时候,可能有人会问,购物车难道不缓存吗,这么多人经常点。购物车做缓存,但是购物车的缓存和商品信息缓存是分开的,哪一家电商的商品信息都是有缓存或者搜索引擎,数据查询比较快。所以不建议缓存整个购物车,而是只缓存商品code,再去查商品详情的缓存进行组合返回给前端。如果说缓存整个购物车(含商品详情),那么尽量设短缓存时间,以便商品信息更新及时。
购物车表结构如下图:
id | productCode | productNum | userId | modelCode(应用code或者渠道号,非必选) |
缓存的设计又分为两个部分,一个部分缓存购物车,也就是上表中的内容,直接key-value结构就行,key就是userId,value就是购物车的json(只存productCode和productNum)。另一个部分是商品选中状态,采用key-map结构,key还是userId,map里面的key是productCode,map的value可以随便设置了,这里用1就行。
这里有一个小插曲,为什么缓存这么设计,购物车主要是考虑直接取出全部商品方便,直接存了一个value的json,而不是考虑更复杂的例如map和list的结构。其次选中状态只需要保存选中,选中了key-map的map里多一个商品code。如果不是选中直接删掉这个map中的key。有人会问长时间不登陆购物车,选中状态不就没了吗?确实就是如此,如果你想加入购物车的商品默认为选中,第一次进入购物车商品全部被选中,那你的key-map缓存中放的就是未选中的商品就行了。还有人会问,那我组选中和全选是否选中是怎么回事,这两个状态都是根据商品是否选中判断的,不是存下来的。大致结构如下所示:
key | value | ||
---|---|---|---|
购物车缓存 | userId | [{"productCode":"productNum"}] | |
商品选中状态缓存 | userId | key | value |
productCode | 1 |
可能看到这里,有人会问,一个缓存就解决问题了,为什么搞两个缓存,多此一举?其实不是,因为购物车缓存是要写到数据库的,选中状态是可以不存数据库的。比如你长时间不登陆app,购物车商品是一直存在的。所以分开更好一些,因为接下来还要考虑购物车的缓存和数据库的冷热数据交换。购物车的操作非常频繁的操作,操作的是缓存热数据,数据库层只是落地,留下永久的痕迹而已。
编码架构
在这里我画了一个图,反而贴我的代码,可能大家看得更晕,不如这种伪代码更容易理解,其中第三步就可以按照你们公司特有的业务来进行价格设置,比如满减,包邮等等。
上面的这个图是一个购物车详情流程。可以将第二步和第三步封装成单独的方法。像加商品,修改商品数量的接口中,都是操作购物车缓存,同时写入购物车数据库,然后调用上图中的第二步与第三步。
结语
我相信很多人看到这里,已经有了自己购物车的原型,大家如果有疑问,或者更好的思路,尽情留言。
购物车-前后端分离版相关推荐
- 若依前后端分离版怎样去掉登录验证码
场景 若依前后端分离版手把手教你本地搭建环境并运行项目: 若依前后端分离版手把手教你本地搭建环境并运行项目_BADAO_LIUMANG_QIZHI的博客-CSDN博客_若依前后端分离版本的配置 上面在 ...
- 若依前后端分离版手把手教你本地搭建环境并运行项目
场景 RuoYi-Vue是一款基于SpringBoot+Vue的前后端分离极速后台开发框架. RuoYi 官网地址:http://ruoyi.vip RuoYi 在线文档:http://doc.ruo ...
- 若依前后端分离版数据库已经存在的字典添加一条后刷新没作用,必须清除Redis缓存
场景 使用若依的前后端分离版,前端下拉框的使用直接查询的是字典表中的数据. 对于某个类型的字典如果之前已经添加过并使用过,后来想要再添加一条此类型的字典. 在数据库中添加后,前端刷新下,发现没有获取到 ...
- 若依前后端分离版怎样根据数据库生成代码并快速实现某业务的增删改查
场景 使用若依的前后端分离版,怎样使用其代码生成实现对单表的增删改查导出的业务. 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程 ...
- 若依前后端分离版怎样修改主页面和浏览器上的图标和标题
场景 使用若依的前后端分离版,,其默认的图标和标题等如下 如果想要修改为自己想要的标题和图标,实现类似下面的效果 注: 博客: https://blog.csdn.net/badao_liumang_ ...
- 若依管理系统前后端分离版基于ElementUI和SpringBoot怎样实现Excel导入和导出
场景 使用若依前后端分离版实现Excel的导入和导出. 前端:Vue+ElementUI 后端:SpringBoot+POI+Mysql 注: 博客: https://blog.csdn.net/ba ...
- 若依前后端分离版怎样修改主页面显示请求的SpringBoot后台数据
场景 使用若依的前后端分离版,本来的首页效果是 现在如果要根据具体业务实现从后台获取要显示的数据实现类似下面的效果 注: 博客: https://blog.csdn.net/badao_liumang ...
- Ruoyi-Vue若依前后端分离版 2022年5月 基于代码生成器的新模块添加
Ruoyi-Vue若依前后端分离版 2022年5月 基于代码生成器的新模块添加 在ruoyi数据库的基础上.编辑好自己的数据库表 启动ruoyi前后端,进系统使用代码生成器 将生成的代码导入到现有的项 ...
- 若依前后端分离版获取部门表所有最子级部门并匹配部门名称生成excel
场景 若依前后端分离版手把手教你本地搭建环境并运行项目: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108465662 在上面 ...
最新文章
- 对WEB前端的几段思考(一)——界面设计和性能优化(整理中)
- 小米手机60帧录屏_手机录屏怎样只录手机内部声音不录入外部声音?教你三种方法,一定能帮到你...
- Oracle数据库创建表空间及用户授权
- JavaScript操作大全整理(思维导图三--函数基础)
- 新浪云python示例_Python Web框架Flask中使用新浪SAE云存储实例
- macbook禁用键盘_一行命令禁用 MacBook 内置键盘
- curl put方法 测试http_HTTP接口调试利器!4.8万Star的HTTP命令行客户端!
- 信息学奥赛一本通(1110:查找特定的值)
- iOS夯实:内存管理
- Halcon Blob分析(二值化图像分割)
- HNUCM-1322:调酒壶里的酸奶
- Python新闻网站项目-9.Django前端HTML功能
- PUBG 绝地逃亡 吃鸡压枪宏 彩虹六号压枪宏 Autohotkey
- MATLAB矩阵的平均值和最大值
- 高分三号卫星(GF-3)简介
- vue @click.native和@click.stop和@click.self
- 计算机主板复位电路的组成,教你认识液晶彩电主板中的复位电路
- 免费常用快递查询API接口及快递在线下单API分享
- python爬虫—Requests
- 如何更高好地管理待办事项?