一, 对商品的数量输入框做限制,change事件,对输入框修改数据后,失去焦点后,对于负数控制
<input autocomplete="off" class="itxt" v-model="skuNum" @change="$event.target.value*1 > 1? skuNum = $event.target.value*1 : skuNum = 1"/>
二,连接路由到去购物车结算页面
<router-link to="/shopcart">去购物车结算</router-link>
三,封装请求购物车列表数据函数
//请求购物车列表数据 /api/cart/cartList get
export const reqShopCartList = () => Ajax.get('/cart/cartList')
四,在shopcart.js的 vuex的actions发送请求,然后在state存储响应数据
五,在ShopCart组件中dispatch到vuex中,但是此时,响应数据是空的,因为到购物车列表页面,此时是没有登录的,
需要搞一个临时身份信息标识uuid,后台存储后,可以识别身份信息
1.新建utils--userabout.js, 封装uuid的函数(用于配置工具函数),在本地localStorage存储一份,向外暴露该函数,安装uuid包,
import { v4 as uuidv4 } from 'uuid';
function getUserTempId(){
//这个是工具函数,它是专门用来生成或者得到用户的临时id的
let userTempId = localStorage.getItem('USERTEMPID_KEY')
//如果获取不到,证明用户之前没有生成过临时id
if(!userTempId){
userTempId = uuidv4() // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
localStorage.setItem('USERTEMPID_KEY',userTempId)
}
//如果存在就直接返回原来的,不存在返回的是新创建的
return userTempId
}
export {
getUserTempId
}
2,新建store--users.js, 引入uuid的函数,存储uuid必须用userTempId存储, 让临时id在vuex中存储,比存储在本地更快
import {} from '@/api'
import {getUserTempId} from '@/utils/userabout'
const state = {
userTempId:getUserTempId()
}
const mutations = {
}
const actions = {
}
const getters = {
}
export default {
state,
mutations,
actions,
getters
}
3.在请求拦截器当中携带uuid,传送给后台,(从vuex中传递)引入import store from '@/store',
注;此时未登录状态下,在ShopCart组件中dispatch到vuex中,响应是有数据的//请求拦截器内部一般不会处理错误的信息
service.interceptors.request.use(config => {
//config是发送请求的配置对象,必须处理完返回这个配置对象
//开启我们的进度条
NProgress.start()
//在请求头当中添加用户的临时id,让每个ajax请求都带着这个userTempId
let userTempId = store.state.user.userTempId
if(userTempId){
config.headers.userTempId = userTempId
}
return config
});
4,shopcart组件从vuex中获取数据,从模板中填充数据
import { mapState } from 'vuex'
computed:{
...mapState({
shopCartList:state => state.shopcart.shopCartList
}),
5,购物车动态数据计算属性数据的展示
模板填充数据
<ul class="cart-list" v-for="(shopcart, index) in shopcartList" :key="shopcart.id"> <li class="cart-list-con1"> <input type="checkbox" name="chk_list" :checked="shopcart.isChecked"> </li> <li class="cart-list-con2"> <img :src="shopcart.imgUrl"> <div class="item-msg">{{shopcart.skuName}}</div> </li> <li class="cart-list-con4"> <span class="price">{{shopcart.skuPrice}}</span> </li> <li class="cart-list-con5"> <a href="javascript:void(0)" class="mins">-</a> <input autocomplete="off" type="text" :value="shopcart.skuNum" minnum="1" class="itxt"> <a href="javascript:void(0)" class="plus">+</a> </li> <li class="cart-list-con6"> <span class="sum">{{shopcart.skuPrice* shopcart.skuNum}}</span> </li> <li class="cart-list-con7"> <a href="#none" class="sindelet">删除</a> <br> <a href="#none">移到收藏</a> </li> </ul>
5.1 , 计算购物车商品的总数
<div class="chosed">已选择 <span>{{checkedNum}}</span>件商品</div> <div class="sumprice">
js代码
checkedNum(){
//统计的数组方法
return this.shopCartList.reduce((pre,item,index)=>{
//已经选中的商品
if(item.isChecked){
pre += item.skuNum
}
// console.log(pre)
return pre
},0)
},
5.2, 计算购物车商品的总价
<div class="sumprice"> <em>总价(不含运费) :</em> <i class="summoney">{{allMoney}}</i> </div>
js代码
allMoney(){
return this.shopCartList.reduce((pre,item,index) => {
if(item.isChecked){
pre += item.skuNum * item.skuPrice
}
return pre
},0)
},
5.3,点击单选框,需要发送请求,更改单选框状态,响应体数据是空
所有单选框选中,全选框自动选上,
点击全选按钮框,所有的单选框都要选上
封装请求修改购物车选中状态函数
//请求修改购物车选中状态 /api/cart/checkCart/{skuID}/{isChecked} get
export const reqUpdateIsChecked = (skuID,isChecked) => Ajax.get(`/cart/checkCart/${skuID}/${isChecked}`)
在vuex中发送该请求
async updateIsChecked({commit},{skuId,isChecked}){
const result = await reqUpdateIsChecked(skuId,isChecked)
if(result.code === 200){
return '修改选中状态成功'
}else{
return Promise.reject(new Error('修改选中状态失败'))
}
},
点击单选框,组件dispatch到vuex,发送请求,修改选择框的状态
<li class="cart-list-con1"> <input type="checkbox" name="chk_list" :checked="cart.isChecked" @click="updateOneIscheck(cart)"> </li>
//修改单个购物车选中状态信息,isChecked状态,1是选中,0是没选中
async updateOneIscheck(cart){
try {
await this.$store.dispatch('updateIsChecked',{skuId:cart.skuId,isChecked:cart.isChecked === 1? 0 : 1})
//重新发送请求,获取新的数据
this.getShopCartList()
} catch (error) {
alert(error.message)
}
}
1.所有单选框选中,全选框自动选上,get方法
2.点击全选按钮框,所有的单选框都要选上, set方法
在组件shopCart点击全选按钮,改变选择框的状态
1.在组件shopCart改变选择框的状态,拿到改变后值,set(ischecked),dispatch到veux的actions的getReqUpdateIsAllChecked,
2.遍历每个选择框的状态,如果有选择框的状态和全选框的状态一致,就不用发送请修改状态的请求了
3.如果有选择框的状态和修改后的全选框的状态不一致,那么dispatch到getReqUpdateIsChecked,修改选择框的状态
4.初始化一个空数组promises, 如果每次dispatch到getReqUpdateIsChecked,那么往数组中添加这个promise
5.然后整体返回一个promsie return Promise.all(promises)
6.在组件中然后在发送请求,获取新的数据, this.getreqShopCartList()
在组件中计算全选按钮的状态
<div class="select-all"> <input class="chooseAll" type="checkbox" v-model="isAllChecked"> <span>全选</span> </div>
js代码
isAllChecked:{
get(){
//返回布尔值,所有单选框选中后,全选框也会跟着选中
return this.shopCartList.every((item,index) => item.isChecked === 1)
},
async set(val){
//点击全选之后,会进入这个set逻辑
try {
const result = await this.$store.dispatch('updateAllIsChecked',val?1:0)
// 重新发送请求,获取新的数据
this.getShopCartList()
} catch (error) {
alert(error.message)
}
}
}
在vuex中处理全选框选中后,单选框的状态变化
//单选框选中发送请求
async updateIsChecked({commit},{skuId,isChecked}){
const result = await reqUpdateIsChecked(skuId,isChecked)
if(result.code === 200){
return '修改选中状态成功'
}else{
return Promise.reject(new Error('修改选中状态失败'))
}
},
//选中全选框的逻辑
updateAllIsChecked({commit,state,dispatch},isChecked){
//定义数组存储每一项去发请求返回的promise对象
let promises = []
state.shopCartList.forEach(item => {
//如果修改后全选按钮的状态和单选的状态一样,不用发送请求,更改状态
if(item.isChecked === isChecked) return
//如果不一致
let promise = dispatch('updateIsChecked',{skuId:item.skuId,isChecked:isChecked})
promises.push(promise)
})
//Promise.all 传递的参数必须是一个promise对象的数组,返回值也是一个promise
//返回的promise对象的成功和失败 看数组内部所有的promise对象是否成功,如果都成功,那么它就成功,如果有一个失败,那它就失败
//成功的返回值promise的数据是一个数组 【每个成功的promise的数据】
return Promise.all(promises)
}
5.4,点击数量加减号,输入框输入数量,发送请求,输入的数量和后台数据库的商品数量做加法,才是修改后的数量
<li class="cart-list-con5"> <a href="javascript:void(0)" class="mins" @click="updateCartNum(cart,-1)">-</a> <input autocomplete="off" type="text" :value="cart.skuNum" minnum="1" class="itxt" @change="updateCartNum(cart,$event.target.value*1)"> <a href="javascript:void(0)" class="plus" @click="updateCartNum(cart,1)">+</a> </li>
js代码
// 修改购物车某个商品的数量 async updateCartNum(cart,changeNum){ //changeNum是后面要发请求的参数,代表的是一个改变的数量 if(cart.skuNum + changeNum < 1){ changeNum = 1 - cart.skuNum } try { //请求修改购物车的商品数量 用原有的数量和改变的数量计算 // await后是同步代码,必须他发送请求,修改数量后,才会立刻执行后面的请求 await this.$store.dispatch('addorUpdateShopCart',{skuId:cart.skuId,skuNum:changeNum}) //请求成功之后,重新获取购物车的列表信息,页面展示的就是最新的 this.getShopCartList() } catch (error) { alert(error.message) } },
vuex发送的请求
const actions = {
async addorUpdateShopCart({commit},{skuId,skuNum}){
const result = await reqAddOrUpdateShopCart(skuId,skuNum)
if(result.code === 200){
return '添加购物车成功'
}else{
// return '添加购物车失败' 返回的还是成功的promise
//返回的是失败的promise
return Promise.reject(new Error('添加购物车失败'))
}
},