一、需求
1、用户选择商品,自动回显在购物车列表中;
2、同个商品追加,购物车列表数量叠加;
3、开启赠送,选中的商品,在购物车中另增一条数据,且购物车列表价格显示为0;其实际价格在最后结算是优惠价格其值是`赠送数量*商品价格`;
4、页面刷新,之前添加的商品依然存在;重新选择商品,依然遵循同类商品数量叠加,新增商品追加在购物车最上面;
5、购物车手动叠加/减数量,在商品列表在选择商品可以实时更新;
6、购物车商品/赠品,单个移除;
7、清空购物车;
二、最终效果
三、实现逻辑
1、选择商品逻辑
1、获取本地缓存,查看是否存在购物车数据;
2、如果不存在——将点击选中的商品数据、排重且数量求和后、存到本地缓存中;
3、如果存在1、判断购物车数据中是否存在现在要加购的商品(使用数组方法find)2、存在该商品——将该商品的数量+13、不存在该商品——与已有商品一起加入到本地缓存中
2、初始化(即刷新后)----初始化获取本地缓存的数据
mounted() {this.cacheHandler()},
methods: {// 获取缓存数据cacheHandler() {// 获取所有数据if (localStorage.getItem('finallyCartList') && JSON.parse(localStorage.getItem('finallyCartList')).length > 0) {this.finallyCartList = JSON.parse(localStorage.getItem('finallyCartList'))this.shoppingCartActive = this.finallyCartList[0]}}
}
3、数量加减——用户增减商品数量,更新本地存储数据
4、删除——filter过滤已经删除的数据,更新本地存储数据
5、清空购物车——清空本地存储数据
6、选择商品关键代码:
// 选择商品itemHandler(item) {const cartObj = JSON.parse(JSON.stringify(item))// 商品数量cartObj.shoppingNum = 1// 是否赠品cartObj.isPresenter = this.isPresenter// 配置购物车列表的唯一值cartObj.soleId = `${cartObj.id}${cartObj.isPresenter}`// 是否配送cartObj.isDistribution = false// 查看本地是否存在购物车数据const store = JSON.parse(localStorage.getItem('finallyCartList') || '[]')if (store.length > 0) {// 判断购物车数据中是否存在现在要加购的商品const currentInfo = store.find(el => {return el.soleId == cartObj.soleId})if (currentInfo) {// 存在数量叠加1currentInfo.shoppingNum = currentInfo.shoppingNum + 1this.finallyCartList = [...store]} else {// 不存在追加在购物车列表前面this.finallyCartList = [cartObj, ...store]}} else {/*** 不存在本地购物车数据逻辑*/this.shoppingCartList = []this.shoppingCartList.push(cartObj)const shoppingCartList = JSON.parse(JSON.stringify(this.shoppingCartList))// 排重且数量求和const result = shoppingCartList.reduce((init, currentValue) => {const leng = init.findIndex(cur => cur.soleId === currentValue.soleId)if (leng != -1) {init[leng].shoppingNum += currentValue.shoppingNum} else {init.push(currentValue)}return init}, [])this.finallyCartList = [...result]}// 把最终购物车列表数据缓存在本地localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))// 购物车列表选中项this.shoppingCartActive = this.finallyCartList[0]// 初始化获取缓存数据this.cacheHandler()// console.log('finallyCartList', this.finallyCartList)}
四、源码
export default {name: 'Checkstand',data() {return {shoppingCartList: [], // 购物车列表finallyCartList: [], // 最终购物车列表shoppingCartActive: {shoppingNum: 1}, // 购物车选中项isPresenter: false, // 是否赠送isDistribution: false // 是否配送}},computed: {// 优惠金额discountsAmount() {return this.finallyCartList.filter(val => val.isPresenter).reduce((retailPrice, currentStudent) => {return retailPrice + (currentStudent.shoppingNum * currentStudent.retailPrice)}, 0)},// 总金额totalAmount() {return this.finallyCartList.filter(val => !val.isPresenter).reduce((retailPrice, currentStudent) => {return retailPrice + (currentStudent.shoppingNum * currentStudent.retailPrice)}, 0)}},mounted() {this.cacheHandler()},methods: {// 获取缓存数据cacheHandler() {// 获取所有数据if (localStorage.getItem('finallyCartList') && JSON.parse(localStorage.getItem('finallyCartList')).length > 0) {this.finallyCartList = JSON.parse(localStorage.getItem('finallyCartList'))this.shoppingCartActive = this.finallyCartList[0]}},// 点击购物车商品activeHandler(item) {this.shoppingCartActive = item},// 选择商品itemHandler(item) {const cartObj = JSON.parse(JSON.stringify(item))// 商品数量cartObj.shoppingNum = 1// 是否赠品cartObj.isPresenter = this.isPresenter// 配置购物车列表的唯一值cartObj.soleId = `${cartObj.id}${cartObj.isPresenter}`// 是否配送cartObj.isDistribution = false// 查看本地是否存在购物车数据const store = JSON.parse(localStorage.getItem('finallyCartList') || '[]')if (store.length > 0) {// 判断购物车数据中是否存在现在要加购的商品const currentInfo = store.find(el => {return el.soleId == cartObj.soleId})if (currentInfo) {// 存在数量叠加1currentInfo.shoppingNum = currentInfo.shoppingNum + 1this.finallyCartList = [...store]} else {// 不存在追加在购物车列表前面this.finallyCartList = [cartObj, ...store]}} else {/*** 不存在本地购物车数据逻辑*/this.shoppingCartList = []this.shoppingCartList.push(cartObj)const shoppingCartList = JSON.parse(JSON.stringify(this.shoppingCartList))// 排重且数量求和const result = shoppingCartList.reduce((init, currentValue) => {const leng = init.findIndex(cur => cur.soleId === currentValue.soleId)if (leng != -1) {init[leng].shoppingNum += currentValue.shoppingNum} else {init.push(currentValue)}return init}, [])this.finallyCartList = [...result]}// 把最终购物车列表数据缓存在本地localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))// 购物车列表选中项this.shoppingCartActive = this.finallyCartList[0]// 初始化获取缓存数据this.cacheHandler()// console.log('finallyCartList', this.finallyCartList)},// 清空购物车clearCart() {this.clearChche()},// 清空数据clearChche() {localStorage.setItem('finallyCartList', JSON.stringify([]))localStorage.setItem('showMemberObj', JSON.stringify({}))this.finallyCartList = []this.shoppingCartActive = {shoppingNum: 1}this.showMemberObj = { ticketCustomers: [] }},// 移除购物车商品delCommodity() {this.finallyCartList = this.finallyCartList.filter(val => this.shoppingCartActive.soleId !== val.soleId)localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))this.shoppingCartActive = this.finallyCartList[0] || { shoppingNum: 1 }this.cacheHandler()},// 配送选中事件changeDistribution(val) {if (!this.shoppingOrTicket) {Toast('请先选择会员!')return}this.finallyCartList.forEach(item => {if (item.id === this.shoppingCartActive.id) {item.isDistribution = val}})localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))},// 每次增减数量重置缓存plusminusHandle() {setTimeout(() => {localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))}, 300)},// 收款collection() {console.log('会员信息', this.showMemberObj)const params = {addressId: this.showMemberObj.addressId || 0,customerId: this.showMemberObj.customerId || 0,customerPhone: this.showMemberObj.customerPhone || '',address: this.showMemberObj.address || '',customerName: this.showMemberObj.customerName || '',operateType: 2,directDiscountAmount: 0,orderStatus: 0,amountReceivable: this.totalAmount,itemMessageDTOList: this.finallyCartList && this.finallyCartList.map(item => { return { itemCode: item.itemCode, qty: item.shoppingNum, itemGiftType: item.isPresenter ? 1 : 0, pickType: item.isDistribution ? 0 : 1 } })}console.log('收款最终参数--会员数据', params)// returnthis.$router.push({ path: '/settleAccounts', query: { data: JSON.stringify(params) } })}}
}
五、相关文章
Vue3 + Vite + Ts开源后台管理系统模板
基于ElementUi或AntdUI再次封装基础组件文档
基于Element-plus再次封装基础组件文档(vue3+ts)