购物车模块( 二)
前言
续上一次的继续 我们搭建了购物车模块 将商品添加到购物车
今天继续 实现查看购物车功能
查看购物车
1.分析
- 用户如果没有登录,购物车存放在浏览器端的localStorage处,且以数组的方式进行存储。
- 用户如果登录了,购物车存放在redis中,以Cart对象字符串方式存储。
- 问题:前后端数据不一致,无法使用一个也flow1.vue进行数据展示
- 解决方案:将后端cart数据进行简化,
Cart对象–>Map(data)–>List(values)
结论:前端提供给页面统一数组,页面进行数据展示即可。
2.接口
GET http://localhost:10010/cart-service/carts
{
"code": 1,
"message": "查询成功",
"data": {
"data": {
"2600242": {
"skuid": 2600242,
"spuid": 2,
"price": 84900.0,
"count": 17,
"checked": true,
"midlogo": null,
"goods_name": "华为 G9 青春版 白色 移动联通电信4G手机 双卡双待",
"spec_info": "{\"id_list\":\"1:1|2:6|6:22\",\"id_txt\":\"{\\\"机身颜色\\\":\\\"白色\\\",\\\"内存\\\":\\\"3GB\\\",\\\"机身存储\\\":\\\"16GB\\\"}\"}"
}
},
"total": 1443300.0
},
"other": {
}
}
3.后端实现
3.1步骤一:修改CartService,添加 queryCartList 方法,从redis查询的购物车信息
/**
*
* @param user
* @return
*/
public Cart queryCartList(User user);
3.2步骤二:修改CartController,添加queryCartList 方法,仅返回购物车中的数据
/**
* 查询购物车
* @param user
* @return
*/
public Cart queryCartList(User user) {
String key = "cart" + user.getId();
// 获取hash操作对象
String cartString = this.stringRedisTemplate.opsForValue().get(key);
// 2 获得购物车,如果没有创建一个
return JSON.parseObject(cartString, Cart.class);
}
3.3 步骤三:修改CartController,添加queryCartList 方法,仅返回购物车中的数据
/**
* 查询购物车
* @return
*/
@GetMapping
public BaseResult queryCartList() {
//1 获得用户信息
// 1.1 获得token
String token = request.getHeader("Authorization");
// 1.2 解析token
User loginUser = null;
try {
loginUser = JwtUtils.getObjectFromToken(token, jwtProperties.getPublicKey(),User.class);
} catch (Exception e) {
return BaseResult.error("token失效或未登录");
}
Cart cart = this.cartService.queryCartList(loginUser);
return BaseResult.ok("查询成功", cart.getData().values());
}
4.前端实现:显示页面
4.1步骤一:创建 ~/pages/flow1.vue 组件,拷贝 ~/static/flow1.html内容
- flow1.vue
<template>
<div>
<!-- 顶部导航 start -->
<TopNav></TopNav>
<!-- 顶部导航 end -->
<div style="clear:both;"></div>
<!-- 页面头部 start -->
<HeaderSeach :isFirst="false"></HeaderSeach>
<!-- 页面头部 end -->
<div style="clear:both;"></div>
<!-- 主体部分 start -->
<div class="mycart w990 mt10 bc">
<h2><span>我的购物车</span></h2>
<table>
<thead>
<tr>
<th class="col1">商品名称</th>
<th class="col2">商品信息</th>
<th class="col3">单价</th>
<th class="col4">数量</th>
<th class="col5">小计</th>
<th class="col6">操作</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col1"><a href=""><img src="images/cart_goods1.jpg" alt="" /></a> <strong><a href="">【1111购物狂欢节】惠JackJones杰克琼斯纯羊毛菱形格</a></strong></td>
<td class="col2"> <p>颜色:073深红</p> <p>尺码:170/92A/S</p> </td>
<td class="col3">¥<span>499.00</span></td>
<td class="col4">
<a href="javascript:;" class="reduce_num"></a>
<input type="text" name="amount" value="1" class="amount"/>
<a href="javascript:;" class="add_num"></a>
</td>
<td class="col5">¥<span>499.00</span></td>
<td class="col6"><a href="">删除</a></td>
</tr>
<tr>
<td class="col1"><a href=""><img src="images/cart_goods2.jpg" alt="" /></a> <strong><a href="">九牧王王正品新款时尚休闲中长款茄克EK01357200</a></strong></td>
<td class="col2"> <p>颜色:淡蓝色</p> <p>尺码:165/88</p></td>
<td class="col3">¥<span>1102.00</span></td>
<td class="col4">
<a href="javascript:;" class="reduce_num"></a>
<input type="text" name="amount" value="1" class="amount"/>
<a href="javascript:;" class="add_num"></a>
</td>
<td class="col5">¥<span>1102.00</span></td>
<td class="col6"><a href="">删除</a></td>
</tr>
<tr>
<td class="col1"><a href=""><img src="images/cart_goods3.jpg" alt="" /></a> <strong><a href="">【1111购物狂欢节】捷王纯手工缝制休闲男鞋大头皮鞋 头层牛</a></strong></td>
<td class="col2"> <p>颜色:0922红棕现货</p> <p>尺码:40现货</p></td>
<td class="col3">¥<span>269.00</span></td>
<td class="col4">
<a href="javascript:;" class="reduce_num"></a>
<input type="text" name="amount" value="1" class="amount"/>
<a href="javascript:;" class="add_num"></a>
</td>
<td class="col5">¥<span>269.00</span></td>
<td class="col6"><a href="">删除</a></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="6">购物金额总计: <strong>¥ <span id="total">1870.00</span></strong></td>
</tr>
</tfoot>
</table>
<div class="cart_btn w990 bc mt10">
<a href="" class="continue">继续购物</a>
<a href="flow2.html" class="checkout">结 算</a>
</div>
</div>
<!-- 主体部分 end -->
<div style="clear:both;"></div>
<!-- 底部版权 start -->
<Footer></Footer>
<!-- 底部版权 end -->
</div>
</template>
<script>
import TopNav from '@/components/TopNav'
import HeaderSeach from '@/components/HeaderSeach'
import Footer from '@/components/Footer'
import BottomNav from '@/components/BottomNav'
import Pagination from '@/components/Pagination'
export default {
components:{
TopNav,
Footer,
HeaderSeach,
BottomNav,
Pagination,
},
}
</script>
<style>
</style>
4.2步骤二:导入js和css
head: {
title: '首页',
link: [
{
rel:'stylesheet',href: '/style/cart.css'},
],
script: [
{
type: 'text/javascript', src: '/js/cart1.js' },
]
},
4.3步骤三:添加公共组件
<script>
import TopNav from '../components/TopNav'
import Footer from '../components/Footer'
export default {
head: {
title: '首页',
link: [
{
rel:'stylesheet',href: '/style/cart.css'},
],
script: [
{
type: 'text/javascript', src: '/js/cart1.js' },
]
},
components: {
TopNav,
Footer,
},
}
</script>
5.前端实现:显示购物车信息
5.1步骤一:修改apiclient.js 查询购物车信息
//查询购物车
getCart : () => {
return axios.get("/cart-service/carts")
},
5.2步骤二:页面加载成功后,获得购物车信息
如果登录从后端获取,如果没有登录从浏览器端获得
data () {
return {
cart: [], //购物车对象
}
},
methods: {
async queryCart() {
// 获得登录标识token
let token = sessionStorage.getItem('token')
if(token) {
// 如果登录状态,发送ajax获得数据
let {
data } = await this.$request.getCart()
this.cart = data.data
} else {
// 如果不是登录状态,从localStorage获得数据
let cartStr = localStorage.getItem('cart')
if(cartStr) {
this.cart = JSON.parse(cartStr)
}
}
},
minus(cartItem) {
if(cartItem.count > 1) {
cartItem.count --
}
},
plus(cartItem) {
cartItem.count ++
},
getSpec(specInfo) {
return JSON.parse(JSON.parse(specInfo).id_txt)
}
},
mounted() {
// 查询购物车
this.queryCart()
},
5.3步骤三:遍历显示购物车信息
<tbody>
<!-- 购物车列表展示start -->
<tr v-for="(cartItem,index) in cart" :key="index">
<td class="col1">
<a href=""><img :src="cartItem.midlogo" alt="" /></a>
<strong><a href="">{
{cartItem.goods_name}}</a></strong>
</td>
<td class="col2">
<span style="display: block;" v-for="(value,key,index) in getSpec(cartItem.spec_info)" :key="index">
{
{key}} : {
{value}}
</span>
</td>
<td class="col3">¥<span>{
{cartItem.price / 100}}</span></td>
<td class="col4">
<a href="javascript:;" class="reduce_num" @click.prevent="minus(cartItem)" ></a>
<input type="text" name="amount" v-model="cartItem.count" value="1" class="amount"/>
<a href="javascript:;" class="add_num" @click.prevent="plus(cartItem)"></a>
</td>
<td class="col5">¥<span>{
{cartItem.price * cartItem.count / 100}}</span></td>
<td class="col6"><a href="">删除</a></td>
</tr>
<!-- 购物车列表展示start -->
</tbody>
5.4步骤四:通过计算属性,计算总价格
computed : {
totalPrice : function(){
//计算总价格
//所有小计的和
let sum = 0 ;
this.cart.forEach( g => {
sum += (g.price * g.count);
});
return (sum/100).toFixed(2);
}
},
感谢宁看到这里,你的三连就是我更新的动力