目录
分析
接口
后端实现
前端实现:显示页面
前端实现:显示购物车信息
分析
- 用户如果没有登录,购物车存放在浏览器端的localStorage处,且以数组的方式进行存储。
- 用户如果登录了,购物车存放在redis中,以Cart对象字符串方式存储。
- 问题:前后端数据不一致,无法使用一个也flow1.vue进行数据展示
解决方案:将后端cart数据进行简化,Cart对象-->Map(data)-->List(values)
结论:前端提供给页面统一数组,页面进行数据展示即可。
接口
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": {}
}
后端实现
- 步骤一:修改CartService,添加 queryCartList 方法,从redis查询的购物车信息
- 步骤二:修改CartController,添加queryCartList 方法,仅返回购物车中的数据
步骤一:修改CartService,添加 queryCartList 方法,
/**
*
* @param user
* @return
*/
public Cart queryCartList(User user);
步骤二:修改CartServiceImpl,从redis查询的购物车信息
/**
* 查询购物车
* @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);
}
步骤三:修改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());
}
前端实现:显示页面
步骤一:创建 ~/pages/flow1.vue 组件,拷贝 ~/static/flow1.html内容
步骤二:导入js和css
head: {
title: '首页',
link: [
{rel:'stylesheet',href: '/style/cart.css'},
],
script: [
{ type: 'text/javascript', src: '/js/cart1.js' },
]
},
步骤三:添加公共组件
<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>
前端实现:显示购物车信息
- 步骤一:修改api.js 查询购物车信息
- 步骤二:页面加载成功后,获得购物车信息(如果登录从后端获取,如果没有登录从浏览器端获得)
- 步骤三:遍历显示购物车信息,
- 步骤四:通过计算属性,计算总价格
步骤一:修改apiclient.js 查询购物车信息
//查询购物车
getCart : () => {
return axios.get("/cart-service/carts")
},
步骤二:页面加载成功后,获得购物车信息(如果登录从后端获取,如果没有登录从浏览器端获得)
data() {
return {
cart : [], //购物车对象
}
},
async mounted() {
//获得token信息,表示登录
this.token = sessionStorage.getItem("token")
if(this.token != null) {
//登陆:服务器获得数据
let { data } = await this.$request.getCart()
this.cart = data.data
} else {
//未登录:从浏览器本地获得购物车
let cartStr = localStorage.getItem("cart");
if(cartStr != null) {
this.cart = JSON.parse(cartStr);
}
}
},
步骤三:遍历显示购物车信息
<tbody>
<!-- 购物车列表 start -->
<tr v-for="(goods,k) in cart" :key="k">
<td class="col1">
<a href=""><img :src="goods.midlogo" alt="" /></a>
<strong><a href="">{{goods.goods_name}}</a></strong>
</td>
<td class="col2">
<span style="display: block;" v-for="(value,key,index) in JSON.parse(JSON.parse(goods.spec_info).id_txt)"
:key="index">{{key}}:{{value}}</span>
</td>
<td class="col3">¥<span>{{ (goods.price/100).toFixed(2) }}</span></td>
<td class="col4">
<a href="javascript:;" class="reduce_num" @click.prevent="minus(goods)"></a>
<input type="text" name="amount" v-model="goods.count" @keyup="updateCount(goods,$event)" value="1" class="amount"/>
<a href="javascript:;" class="add_num" @click.prevent="plus(goods)"></a>
</td>
<td class="col5">¥<span>{{ (goods.price / 100 * goods.count).toFixed(2) }}</span></td>
<td class="col6"><a href="" @click.prevent="del(k)">删除</a></td>
</tr>
<!-- 购物车列表 end -->
</tbody>
步骤四:通过计算属性,计算总价格
computed : {
totalPrice : function(){ //计算总价格
//所有小计的和
let sum = 0 ;
this.cart.forEach( g => {
sum += (g.price * g.count);
});
return (sum/100).toFixed(2);
}
},