首先,祝各位大佬节日快乐,永无bug!
前言:言归正传,本文实现购物车的思路是:获取后端的商品列表——前端本地缓存添加的商品数据——从缓存中获取数据渲染到购物车页面——从缓存中获取数据并提交订单。所以主要是购物车数据的存和取以及清除。
商品选择页面
分析:考虑到商品列表会多处使用,并且增加、减少商品数量的操作都是一样的,所以将右侧的列表做成组件。
/*shopListRight.vue*/
<template>
<div class="shopListRight">
<div class="view-box">
<i class="ifont i-logo"></i>
<div class="view-box-item" v-for="(item,index) in listData" :key="index">
<div class="img">
<img v-if="item.imgPath" :src="item.imgPath">
<img v-else src="../assets/images/img_bg.png">
</div>
<div class="con-right">
<div class="con-right-title">{
{
item.goodsName}}</div>
<div class="con-right-bottom">
<div class="con-right-bottom-price">¥ {
{
item.price}}</div>
<div class="con-right-botton-count">
<img v-if="item.count" src="../assets/images/goods_reduce.png" @click="delCount(item)">
<span v-if="item.count">{
{
item.count}}</span>
<img src="../assets/images/goods_add.png" @click="addCount(item)">
</div>
</div>
</div>
</div>
</div>
</div>
</template>
组件的样式
.shopListRight {
background: #fff;
}
.view-box-item {
display: flex;
margin-bottom: 2.03rem;
}
.view-box-item:last-of-type {
margin-bottom: 0px;
}
.view-box-item > .img {
width: 3.75rem;
height: 3.75rem;
margin-right: 0.9rem;
background: #f6f6f7;
}
.view-box-item > .img > img {
width: 100%;
height: 100%;
}
.view-box-item .con-right {
flex: 1;
position: relative;
}
.view-box-item .con-right .con-right-title {
font-size: 0.87rem;
font-weight: bold;
color: #333;
}
.view-box-item .con-right .con-right-bottom {
position: absolute;
width: 100%;
bottom: -0.3rem;
display: flex;
justify-content: space-between;
}
.view-box-item .con-right .con-right-bottom .con-right-bottom-price {
padding-top: 0.3rem;
font-size: 0.75rem;
font-weight: bold;
color: #fe9900;
vertical-align: middle;
}
.view-box-item .con-right .con-right-bottom .con-right-botton-count > span {
vertical-align: middle;
margin: 0 0.503rem;
}
.view-box-item .con-right .con-right-bottom .con-right-botton-count > img {
width: 1.56rem;
height: 1.56rem;
vertical-align: middle;
}
购物车逻辑处理
export default {
data() {
return {
totalMoney: 0,
totalNum: 0,
carList: []
}
},
props: {
listData: {
type: Array,
default: () => []
}
},
methods: {
// 减数量
delCount(item) {
let carList = JSON.parse(localStorage.getItem('carList')) || []
let index = carList.map(res => res.goodsId).indexOf(item.goodsId)
if (index > -1 && carList[index].count > 0) {
//购物车中已存在点击添加的商品
carList[index].count--
}
let index2 = this.listData.map(item => item.goodsId).indexOf(item.goodsId)
if (this.listData[index2].count > 0) {
this.listData[index2].count--
if (this.listData[index2].count == 0) {
//减到数量为0时从购物车中移除该商品
let index = carList.map(res => res.goodsId).indexOf(this.listData[index2].goodsId)
carList.splice(index, 1)
}
}
localStorage.setItem('carList', JSON.stringify(carList))
this.$emit('initCarList')
this.priceCount()
this.numCount()
},
// 增加数量
addCount(obj) {
let item = obj
let index2 = this.listData.map(res => res.goodsId).indexOf(item.goodsId)
this.listData[index2].count++
let carList = JSON.parse(localStorage.getItem('carList')) || []
let index = carList.map(res => res.goodsId).indexOf(item.goodsId)
if (index > -1) {
//购物车中已存在点击添加的商品
carList[index].count++
} else {
//购物车不存在点击的商品
item.count = 1
carList.push(item)
}
localStorage.setItem('carList', JSON.stringify(carList))
this.priceCount()
this.numCount()
},
// 计算总价
priceCount() {
let carList = JSON.parse(localStorage.getItem('carList')) || []
let totalMoney = 0
carList.map(res => {
totalMoney += (res.price) * (res.count)
})
localStorage.setItem('totalMoney', totalMoney)
this.$emit('getCountMoney', totalMoney)//向外传递数据
},
// 计算选购数量
numCount() {
let carList = JSON.parse(localStorage.getItem('carList')) || []
let totalNum = 0
carList.map(res => {
totalNum += res.count
})
localStorage.setItem('totalNum', totalNum)
this.$emit('getCountNum', totalNum)//向外传递数据
}
}
}
在页面使用组件
<shopListRight :listData="listData" @getCountMoney="getCountMoney" @getCountNum="getCountNum"></shopListRight>
页面逻辑
data() {
return {
listData: [],//这是你需要渲染商品列表的数据
}
},
methods:{
//监听组件的事件、购物车数据变化时会将购物车的数量和对应的总金额传到页面中
getCountMoney(value) {
this.totalMoney = value.toFixed(2)
},
getCountNum(value) {
this.totalNum = value
}
}
购物车页面
页面代码
<template>
<div class="carlist">
<div class="carlist-hand">
<div class="carlist-hand-total">共计{
{
totalNum}}件商品</div>
<div class="carlist-hand-right" @click="clearAll">
<img src="../../assets/images/delete_icon.png">
<span>清空购物车</span>
</div>
</div>
<div class="scroll-div">
<div class="scroll-div-con" v-if="carList.length">
<shopListRight :listData="carList" @getCountMoney="getCountMoney" @getCountNum="getCountNum" @initCarList="initCarList"></shopListRight>
</div>
<div class="empty-data" v-else>
<i class="empty-icon iconfont icon-caution"></i>
<span>暂无数据</span>
</div>
</div>
<div class="bottom-tab">
<div class="flex-box">
<div class="bottom-tab-box-price">¥{
{
totalMoney}}</div>
<div class="bottom-tab-right" @click="goTosettlement">
<div class="car-title">去结算</div>
</div>
</div>
</div>
</div>
</template>
页面逻辑
<script>
import {
Dialog } from 'vant'
import shopListRight from "@/components/shopListRight"
export default {
components: {
shopListRight, [Dialog.Component.name]: Dialog.Component },
data() {
return {
carList: [],
totalMoney: 0,
totalNum: 0,
loading: true,
storeId: '',
}
},
activated() {
},
mounted() {
this.initCarList()
let query = this.$route.query
this.storeId = query.storeId
let totalMoney = localStorage.getItem('totalMoney') || 0
this.totalMoney = Number(totalMoney).toFixed(2)
this.totalNum = localStorage.getItem('totalNum') || 0
},
methods: {
initCarList() {
this.carList = JSON.parse(localStorage.getItem('carList')) || []
},
getCountMoney(value) {
this.totalMoney = value.toFixed(2)
},
getCountNum(value) {
this.totalNum = value
},
// 清空购物车
clearAll() {
Dialog.confirm({
title: '提示',
message: '请确认是否清空购物车所有商品?',
confirmButtonText: '确认',
confirmButtonColor: '#999',
cancelButtonText: '我再想想',
cancelButtonColor: '#ff6600'
}).then(() => {
this.carList = []
this.totalNum = 0
this.totalMoney = 0
localStorage.setItem('listData', [])
localStorage.setItem('carList', [])
localStorage.setItem('totalNum', 0)
localStorage.setItem('totalMoney', 0)
})
},
// 去结算
goTosettlement() {
this.$router.push({
path: './confirmOrder', query: {
isSettlement: true, storeId: this.storeId } })
},
},
}
</script>
最终缓存是这样的存在:
totalNum:记录购物车的选的数量
carList:记录加入购物车的所有商品信息
totalMoney:记录购物车中所有商品的价格
listData:组件渲染的数据
看效果
以上就是h5实现购物车功能的全部了,有问题评论区见!