【Vue项目】尚品汇(六)ShopCar组件开发 购物车模块
2022/9/3 23:25:09
本文主要是介绍【Vue项目】尚品汇(六)ShopCar组件开发 购物车模块,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
4 购物车
4.1 购物车商品数量控制
Detail\index.vue
<div class="cartWrap"> <div class="controls"> <input v-model="skuNum" @change="changeSkuNum" autocomplete="off" class="itxt"> <a href="javascript:" class="plus">+</a> <a href="javascript:" class="mins">-</a> </div> <div class="add"> <a href="javascript:">加入购物车</a> </div> </div>
// 商品数量 changeSkuNum(event) { let value = event.target.value * 1 if(isNaN(value) || value < 1 || value > 999) { console.log('非法数据') } else { this.skuNum = parseInt(value) } },
通过* 1的方式判断是否输入为非数字,因为非数字乘1的话会变为undefined
4.2 购物车路由跳转
分析:添加购物车需要两个数据:sku_num和sku_id,服务器返回的数据只是成功或者失败不会返回其他信息。
- 编写api
// api/cart/addToCart/{ skuId }/{ skuNum } export const reqAddOrUpdateShopCar = (skuId, skuNum) => { return requests({ url:`/cart/addToCart/${skuId}/${skuNum}`, method: 'post' }) }
- vuex编写actions
const actions = { async getDetailInfo(context, skuId) { let result = await reqGetDetailInfo(skuId); if(result.code === 200) { context.commit('GETDETAILINFO', result.data); } }, async addOrUpdateShopCar({context}, {skuId, skuNum}) { let result = await reqAddOrUpdateShopCar(skuId, skuNum) if(result.code === 200) { return 'ok'; } else { return Promise.reject(new Error('fail')); } } }
不需要再写mutations和state仓库了,因为没有返回数据
后面请求头写完uuid后会产生数据
- 编写路由信息
{ path: '/addShopCarSuccess', component: AddCartSuccessrt, name: 'addShopCarSuccess', meta: { showFooter: true } }
- 根据返回的结果进行响应路由跳转
// 购物车添加 async addShopCar() { try{ await this.$store.dispatch('addOrUpdateShopCar', { skuId : this.skuInfo.id, skuNum : this.skuNum }); this.$router.push({name: 'addShopCarSuccess'})// 路由跳转 } catch (error) { alert(error.message) } }
4.3 路由传参结合回话存储传递数据
分析:H5新增的两种存储:本地存储(localstorage)
和会话存储(sessionstorage)
,这里应该使用sessionstorage,因为vue是单页面应用到网页关闭只有一个会话。可以使用路由query
传递skuNum
而用sessionstorage
存储skuInfo
和squSaleAttrList
- 将信息存入sessionstorage
Detail/index.vue
// 购物车添加 async addShopCar() { try{ await this.$store.dispatch('addOrUpdateShopCar', { skuId : this.skuInfo.id, skuNum : this.skuNum }); // 路由跳转 this.$router.push({name: 'addShopCarSuccess', query:{skuNum: this.skuNum}}) sessionStorage.setItem('skuInfo', JSON.stringify(this.skuInfo)) sessionStorage.setItem('spuSaleAttrList', JSON.stringify(this.spuSaleAttrList)) } catch (error) { alert(error.message) } }
4.4 请求头加入uuid判断游客身份
分析
:可以在本地存储localstorage设置一个uuid,然后每次请求都携带这个uuid,后端就能通过这个uuid在不登录的情况下判断用户返回相应的数据了。那么首先这个uuid应该存储在store仓库中,然后需要一个接口函数能够判断localstorage中有没有uuid,如果没有则创建有则直接返回仓库,最后也是最重要的一步,应该在请求拦截器中的config参数设置uuid,如此发出的请求就能携带uuid了。
- 编写uuid生成接口 \utils\uuid_token.js
import { v4 as uuidv4 } from 'uuid'; export const getUUID = () => { let uuid_token = localStorage.getItem('UUID_TOKEN') if(uuid_token) { return uuid_token } uuid_token = uuidv4() localStorage.setItem('UUID_TOKEN', uuid_token) return uuid_token }
- 在vuex仓库中生成uuid \store\detail\index.js
import {getUUID} from '@/utils/uuid_token' const state = { detailInfo: {}, uuid_token: getUUID() }
随便找一个模块仓库放就可以
- 在请求拦截器中config添加携带仓库中的uuid
import store from '@/store' // 请求拦截器,在请求发出之前能够检测到,做一些指定的业务 requests.interceptors.request.use((config)=>{ // console.log(store.state.detail.uuid_token) nprogress.start(); // 参数为config的回调函数 // config为配置对象,包含一个中要的属性headers请求头 if(store.state.detail.uuid_token) { config.headers.userTempId = store.state.detail.uuid_token } return config; });
userTempId为前后端协商的字段不可修改
再次进入购物车页面
,可以看到购物车接口可以返回之前加入购物车的数据了。
注意是购物车页面,添加购物车页面是不返回任何数据的
4.5 更新购物车商品数量
更新的接口和添加的结构是相同的,只是,num为负数表示减少为正数表示添加。
export const reqAddOrUpdateShopCar = (skuId, skuNum) => { return requests({ url:`/cart/addToCart/${skuId}/${skuNum}`, method: 'post' }) }
其他没有特别的点,记得发完请求之后再重新获取下页面参数
<li class="cart-list-con5"> <a @click="skuNumHandler('minus', cartInfo, -1)" class="mins">-</a> <input autocomplete="off" type="text" @change="skuNumHandler('change', cartInfo, $event.target.value * 1)" :value="cartInfo.skuNum" minnum="1" class="itxt"> <a @click="skuNumHandler('add', cartInfo, 1)" class="plus">+</a> </li>
methods: { getData() { this.$store.dispatch('getCarList') }, async skuNumHandler(type, cartInfo, disNum) { switch(type) { case 'add': disNum = 1; break; case 'minus': disNum = cartInfo.skuNum > 0 ? -1 : 0 break; default: disNum = isNaN(disNum) ? 0 : disNum - cartInfo.skuNum break; } console.log(disNum) await reqAddOrUpdateShopCar(cartInfo.skuId, disNum) // console.log(result.data) this.getData() } }
4.6 删除购物车商品
没啥特别的,直接上代码了
\api\index.js
// /api/cart/deleteCart/{skuId} export const reqDeleteCarList = (skuId) => { return requests({ url: `/cart/deleteCart/${skuId}`, method: 'delete' }) }
\store\shopCar\index.js
async deleteCarInfo(context, skuId) { let result = await reqDeleteCarList(skuId) if(result.code === 200) { return 'ok' } else { return Promise.reject(new Error('failed')) } }
\pages\ShopCar\index.vue
async deleteCarInfo(skuId) { try { await this.$store.dispatch('deleteCarInfo', skuId) this.getData() }catch (err) { alert(err.message) } }
4.7 购物车商品修改的节流
可以发现在快速修改商品数量的时候会变成负数,因此需要对函数做节流,具体参照之前的随笔:【Vue项目】商品汇前台(二)进度条插件+Vuex模块化仓库+函数的防抖与节流+路由传参 - Tod4 - 博客园
skuNumHandler: throttle(async function (type, cartInfo, disNum) { switch (type) { case 'add': disNum = 1; break; case 'minus': disNum = cartInfo.skuNum > 1 ? -1 : 0 break; default: disNum = (isNaN(disNum) || disNum < 1) ? 1 : parseInt(disNum) - cartInfo.skuNum break; } await reqAddOrUpdateShopCar(cartInfo.skuId, disNum) // console.log(result.data) this.getData() }, 500),
4.8 修改产品是否选中的状态
也没啥特别的
\api\idnex.js
// /api/cart/checkCart/{skuID}/{isChecked} export const reqCheckCart = (skuID, isChecked) => { return requests({ url: `/cart/checkCart/${skuID}/${isChecked}`, method: 'get' }) }
vuex \store\shopCar\index.js
async checkCart(context, {skuId, isChecked}) { let result = await reqCheckCart(skuId, isChecked) if(result.code === 200) { return 'ok' } else { return Promise.reject(new Error('failed')) } }
\pages\shopCar\index.vue
async changeIsChecked(skuId) { let isChecked = event.target.checked ? 1 : 0 try { await this.$store.dispatch('checkCart', { skuId: skuId, isChecked: isChecked }) this.getData() }catch (err) { alert(err.message) } }
4.9 ☆ 删除所选的商品
分析
:接口中没有删除多个商品的,因此需要多次调用之前的按照商品ID单独删除商品的接口,可以在仓库中创建一个action使用上下文context多次调用之前的单独删除的actiondeleteCarInfo
,而调用action会返回promise,因此需要对多个promise执行一次Promise.all()才能得到五次的结果。
Promise.all()中的一个promise执行失败,则全部的promise都会失败
- 编写仓库删除多个商品的action
\store\shopCar\index.js
deleteAllCheckedCar({dispatch, getters}) { let promises = [] getters.cartInfoList.cartInfoList.forEach(item => { if(item.isChecked === 1) { let promise = dispatch('deleteCarInfo', item.skuId) promises.push(promise) } }) return Promise.all(promises) },
- 编写组件的派发action的方法
\pages\ShopCar\index.vue
async deleteAllCheckedCar() { try { await this.$store.dispatch('deleteAllCheckedCar') this.getData() }catch (err) { alert(err.message) } },
4.10 修改多个商品的选中状态
与上面差不多,直接贴代码了
\pages\ShopCar\index.vue
changeAllCheckedCar({dispatch, getters}, isChecked) { let promises = [] getters.cartInfoList.cartInfoList.forEach(item => { let promise = dispatch('checkCart', { skuId: item.skuId, isChecked: isChecked }) promises.push(promise) }) return Promise.all(promises) }
\store\shopCar\index.js
async changeAllCheckedCar() { try{ let isChecked = event.target.checked ? 1 : 0 await this.$store.dispatch('changeAllCheckedCar', isChecked) this.getData() }catch (err) { alert(err.message) } }
这篇关于【Vue项目】尚品汇(六)ShopCar组件开发 购物车模块的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-26React入门教程:从零开始搭建你的第一个React应用
- 2024-12-25Vue2入门教程:轻松掌握前端开发基础
- 2024-12-25Vue3入门指南:快速搭建你的第一个Vue3项目
- 2024-12-25JS基础知识入门教程
- 2024-12-25React基础知识详解:从入门到初级应用
- 2024-12-25Vue3基础知识详解与实战指南
- 2024-12-25Vue3学习:从入门到初步掌握
- 2024-12-25Vue3入门:新手必读的简单教程
- 2024-12-23【JS逆向百例】爱疯官网登录逆向分析
- 2024-12-21Vue3教程:新手入门到实践应用